Na navigaci | Klávesové zkratky

Translate to English… Ins Deutsche übersetzen…

Objevena první zranitelnost v Nette, aktualizujte!

Hurá, Nette už má první záznam v CVE! To znamená, že v něm byla objevena první vážná zranitelnost. Co se vlastně stalo?

Na konci prázdnin mi napsal vývojář Cyku Hong z malebného Taiwanu, že našel v Nette zranitelnost a v následujícím e-mailu vysvětlil princip možného zneužití. Ověřil jsem, že jde o uskutečnitelný útok. Dovoluje útočníkovi za určitých okolností na některých webech pomocí speciálně sestaveného URL spustit kód, tedy jde o zranitelnost Remote code execution (RCE). Cyku, díky!

Musím říct, že to bylo v 13leté historii frameworku Nette vlastně poprvé, co někdo našel takto závažnou zranitelnost. Dříve byly několikrát reportovány drobné záležitosti, např. letos v březnu Jan Gocník odhalil možnou zranitelnost v případě, že by programátor deserializoval a vypsal query proměnnou echo unserialize($_GET['a']), což je samo o sobě principiálně velmi nebezpečné, nicméně jeho nález jsem samozřejmě opravil. Také jsem dostal řadu hlášení, které nebyly opodstatněné, například že uploadovaný obrázek vyhovující testu isImage() může v sobě obsahovat PHP kód. Což samozřejmě může, například v metadatech, ale není to bezpečnostní problém Nette.

Ale zpět k chybě, o které je tento článek. Bezprostředně po nahlášení jsem ji opravil a vydal nové verze balíčků nette/application a nette/nette.

Nejstarší zasaženou verzí bylo Nette 2.0, které už sice není 6 let udržované, ale protože Nette má bezpečnost jako jednu z priorit, vydal jsem nové verze také u všech nepodporovaných verzí. Což je ve světě opensource frameworků ojedinělý krok. Díky tomu mohou uživatelé snadno a bez prodlení aktualizovat nejen projekty udržované a běžící na současných verzích, ale i projekty s technologickým dluhem. Vlastně se teď dá říci, že každá řada Nette je nejen Long-Term Support Release (tedy podporovaná alespoň dva roky, viz tabulka), ale z pohledu bezpečnostních fixů i Forever-Term Supported 🙂

Druhým krokem bylo o chybě informovat. Samotné zveřejnění chyby na blogu by i bez podrobného popisu zneužití představovalo vodítko pro darebáky, kteří by se o chybě dozvěděli a mohli se pokusit ji zneužít. Proto mi připadalo fér nejprve informovat všechny podporovatele Nette, poté i další uživatele na které mám kontakt a teprve s určitým časovým odstupem publikovat oznámení veřejně na blogu, GitHubu a katalogu CVE. Prostě dát partnerům určitý čas zaktualizovat všechny weby dříve, než by se objevil první útočník. Původně jsem zamýšlel dát odstup týden, ale pak jsem na základě diskusí pochopil, že to je doslova šibeniční termín a vhodnější je dát alespoň 2–4 týdny.

Jak už jsem zmiňoval, šlo o mou první zkušenost s takovou situací, ale chtěl jsem ji zvládnout příkladně. Abych se nedopustil žádného přešlapu, napsat jsem Michalu Špačkovi, kterého považuji za nejlepšího odborníka v této oblasti, a všechno s ním konzultoval. Michal mi schválil postup, dal řadu užitečných rad, připomínkoval emaily atd. Michale, moc děkuji!

Ačkoliv žádný z mnou provozovaných webů nebyl tímto způsobem zranitelný, prohledal jsem jejich access logy za posledních 8 let (co díra existuje) a zjistil, že tento typ útoku na ně historicky nikdo nezkusil. Soudím, že na zranitelnost nikdo dříve nepřišel. Útočníci totiž obvykle zkouší testovat také přímo web nette.org.

Nechci zveřejňovat přesný postup zneužití chyby a doufám, že to ani nikdo jiný neudělá. Alespoň ne v dohledné době, protože by tím způsobil ostatním nepříjemnosti a zpronevěřil se duchu open source.

Aktualizujte prosím co nejdříve na nejnovější setinkové verze:

  • nette/application 3.0.6 (případně 3.0.2.1, 3.1.0-RC2 nebo dev)
  • nette/application 2.4.16
  • nette/application 2.3.14
  • nette/application 2.2.10
  • nette/nette 2.1.13
  • nette/nette 2.0.19

Nejrychlejší oprava

Michal připravil Linuxový skript a já obdobu v PHP, který automaticky aplikuje patch přímo do zdrojových kódů Nette na disku. Hodí se v případě, že udržujete velké množství projektů, které nemáte čas korektně aktualizovat pomocí Composeru.

Informaci o chybě rozeslal emailem svým klientům VSHosting, WEDOS nebo HostingBB, zároveň některé hostingy přímo blogují problematickou URL, případně rovnou aplikovaly výše uvedený fix. Díky!!!

Komentáře

  1. sucho #1

    avatar

    Ja som v poslednej dobe sledoval celkom podivné logy
    samozrejme veľa bolo takých ako by sa skúšal niekto dostať do Wordpresu a teda samé wp-admin
    ale potom bolo pomerne dosť URL s podivnými [zatvorkovými] parametrami

    potom sa mi aj na FTP začali objavovať divné index.php súbori a potom nejaké s úplne divným názvom a obsahom
    a po konzultácii s hostingom sme zistili že bol to útok
    taktiež som to vyhľadal cez access.log konkrétnu IP a dané POST requesty a celé FTP som premazal

    čo bolo horšie na tom jednom hostingu som mal 12 projektov a bolo to vo všetkých ale v Nette som mal len ten jeden hlavný ostatné boli Wordpress a OpenCart …a teda neviem odkiaľ tie súbory vznikli či práve cez Nette alebo skôr dieru v inom projekte

    před 2 měsíci | odpovědět | reagoval [2] David Grudl
  2. David Grudl https://davidgrudl.com #2

    avatar

    #1 sucho, tyhle logy, co popisuješ, jsou zcela běžné už drahně let, jde o automatizované útoky na Wordpress a další populární projekty. (Nemusí vůbec na webu běžet.)

    Když je v katalogu CVE vyhledáš, zjistíš, že těch bezpečnostních chyb mají opravdu hodně a je nutné je všechny pravidelně aktualizovat.

    Další věc je, že se běžně kradou FTP přístupy, ať už „po cestě“, pokud nepoužíváš šifrované spojení, nebo se vykrádají různé Total Commandery a podobně, kde jsou spojení uložená včetně hesel. Darebáci se pak připojují přímo na FTP a modifikují soubory nebo nahrávají nějaké další, obvykle právě index.php.

    před 2 měsíci | odpovědět
  3. Lukáš #3

    avatar

    Budou prosím aktualizované verze k dispozici ke stažení jako zip v archivu starších verzí ?

    před 2 měsíci | odpovědět | reagoval [4] David Grudl
  4. David Grudl https://davidgrudl.com #4

    avatar

    #3 Lukáši, doplnil jsem je

    před 2 měsíci | odpovědět | reagoval [5] Lukáš
  5. Lukáš #5

    avatar
    před 2 měsíci | odpovědět
  6. Vláďa #6

    avatar

    Dá se předpokládat, že tento exploit funguje to i na pre-release 2.0?
    Používám tuto úžasnou verzi Nette:
    version 2.0-dev released on 2011–10–12

    před měsícem | odpovědět | reagoval [12] Michal Špaček [13] David Grudl
  7. Marek #7

    avatar

    Davide to s tím isImage jsem reportoval já a absolutně s tebou nesouhlasím. Pokud metoda isImage kontroluje pouze hlavičku co příjde od klienta je to špatně, porgramátor volá v kodu pak isImage a spoléha na fakt ze nette isImage osetri správně a ehle nem ono tam může být PHP kod jen klient NETTE řekl je to JPG/PNG/GIF a pak to projde touto validací, tedy vlastně je to metoda k ničemu. Kdybys mi odpověděl tenkrát na email mohli jsme o tom vést diskuzi, tak jí můžem vést tady i s ostatnimi navíc Michal Špaček na některých přednáškách říká ze ošetrovat na zakladě hlaviček je chybně, když se dají podvrhnout. Mimochodem díky této chybě jsem hacknul nespočet webů postavený na nette.

    před měsícem | odpovědět | reagoval [8] Michal Špaček [13] David Grudl
  8. Michal Špaček https://www.michalspacek.cz #8

    avatar

    #7 Marku, Když už jsem i v komentářích… 🙂 Pokud metoda isImage kontroluje pouze hlavičku co příjde od klienta: FileUpload::isImage() se kouká na typ souboru, do samotného souboru, ne do HTTP hlaviček. A dělá to tak aspoň 10 let, to je udělané správně. Browser musí poslat soubor s GIF hlavičkou, aby Nette mohlo říct, že to je GIF, co o souboru tvrdí klient je nepodstatné.

    před měsícem | odpovědět
  9. Andrej #9

    Byl záměr, že v Nette 3 je to ošetřeno vyhozením Nette\InvalidStateException a ve starších verzích Application\BadRequestException? Proč?

    před měsícem | odpovědět | reagoval [13] David Grudl
  10. Vít Sikora #10

    Bylo by prosím možné zveřejnit nějaký closed-source nástroj, kde člověk zadá URL adresu a nástroj zkontroluje, zda je projekt zranitelný? Máme mnoho starých nette projektů, kde se např. používá jen malá část frameworku (staženého, ne přes composer, v2.0) a bylo by nákladné to opravovat. Hlavně bych chtěl zjistit, zda je to vůbec napadnutelné.

  11. Andrej #11

    #10 Víte Sikoro, Access log mám zaprasenej requestama z https://www.salamek.cz/nette-test.php

    před měsícem | odpovědět | reagoval [16] Michal Špaček
  12. Michal Špaček https://www.michalspacek.cz #12

    avatar

    #6 Vláďo, Ano, dá se více než úspěšně předpokládat, že „version 2.0-dev released on 2011–10–12“ je také zranitelná.

    před měsícem | odpovědět | reagoval [15] Salamek
  13. David Grudl https://davidgrudl.com #13

    avatar

    #6 Vláďo, nemám archiv těchto verzí, ale můžeš ji fixnout tak, že smažeš soubor MicroPresenter.php, pokud tam je. Ale bál bych se, že v deset let staré nestable verzi budou onačejší problémy.

    #7 Marku, můžeš mi napsat do emailu postup jak tímto způsobem hackuješ web na nette?

    #9 Andreji, v další verzi nette/application to bude zpátky BadRequestException

    #10 Víte Sikoro, v takové situaci, kdy nepoužíváš composer, můžeš použít automatizovaný nástroj napsaný v php nebo shellu

    před měsícem | odpovědět | reagoval [19] Marek
  14. Miloš #14

    Aktualizujte, útoky na tenhle exploit už běžej od blackhatů. Nahráli nám na server nějaké části wordpressu ale asi se jim nepodařilo útok zprovoznit, index ale házel 500 na chybějících součástech.
    https://www.abuseipdb.com/….165.211.206

    před měsícem | odpovědět
  15. Salamek #15

    #12 Michale Špačku, To je tool na kontrolu zda li je web děravý, nějaký white hat jej volá z Python crawleru a parsuje mailto z vulnerable webu kam posila emaily s infem o nutnosti aktualizace… více info na https://www.abclinuxu.cz/…testing-tool
    #10 Vít Sikora Viz ^

    před měsícem | odpovědět | reagoval [16] Michal Špaček
  16. Michal Špaček https://www.michalspacek.cz #16

    avatar

    #15 Salamku, Zatracený off-by-one chyby, to asi měla být reakce na #11 Andrej 🙂

    před měsícem | odpovědět
  17. Jan Nový #17

    avatar

    Tato zranitelnost může způsobit kompromitaci vaší databáze aniž by jste si toho vůbec museli všimnout. I když vám web funguje normálně mohl si útočník odnést kompletní databázi, privátní klíče a jiná data uložená mimo veřejně dostupný adresář aplikace. Po aktualizaci si zkontrolujte access log.

    před měsícem | odpovědět
  18. Martin Pištora #18

    avatar

    Pokud hostingy problematickou URL přímo blogují, tak se mohla zveřejnit i zde. Spíše by ji měly blokovat.

    před měsícem | odpovědět
  19. Marek #19

    avatar

    #13 Davide Grudle, Já když zpětně po sobě četl co jsem ti psal, tak to nebylo dobře napsané. Popis a i uvažování proč si to myslím jsem ti hodil na email. Samozřejmě pokud stále vyhodnotíš, že za to nemůže samotné nette, ale bud PHP finfo_file či programátor co to chybně používá, tak by to v tom případě v nette být nemělo ať si validaci na image dělá programátor sám, ale když jí tam máš, měla by skutečně zvalidovat IMAGE nikoliv, že přes tu validaci projde i PHP které půjde pustit, pak je chybně napsaná právě ta validace. Vše máš v emailu.

    před měsícem | odpovědět | reagoval [21] David Grudl
  20. antijouda #20

    Tak jsem alespoň zjistil, že mi na webu chyběla složka nette.

    před měsícem | odpovědět | reagoval [22] antijouda
  21. David Grudl https://davidgrudl.com #21

    avatar

    #19 Marku, shrnu ten email pro zdejší čtenáře: poukazuješ na problém způsobený tím, že programátor uloží do veřejného adresáře uploadovaný soubor pod názvem podstrčeným útočníkem. Např. obrázek uloží pod názvem image.php a pak jej lze pochopitelně spustit na serveru.

    To samozřejmě je fatální chyba. Ale programátora, nikoliv validátoru obrázku.

    • Jednak to se netýká jen obrázků, ukládat pod podstrčeným názvem nelze ani nic jiného.
    • Zároveň není možné zahazovat obrázky, které v sobě „obsahují PHP“. Rychlým testem jsem zjistil, že pětina mých fotek obsahuje náhodně bajty shodné s otevírací značkou PHP <?=. A jde o zcela platné obrázky.

    Co by se dalo udělat z pohledu Nette? V docce i phpDoc je řečeno, že názvu od klienta se nesmí důvěřovat. Asi by byl dobrý nápad přejmenovat metodu getName() na getUntrustedName() apod. Ale validátor obrázků je imho uplně ok.

    před měsícem | odpovědět
  22. antijouda #22

    #20 antijoudo,
    ou, tak už mi na web nahráli nějaký servershell.php, 16.10.

    před měsícem | odpovědět

Zanechat komentář

Text komentáře
Kontakt

(kvůli gravataru)



*kurzíva* **tučné** "odkaz":http://example.com /--php phpkod(); \--

phpFashion © 2004, 2020 David Grudl | o blogu

Ukázky zdrojových kódů smíte používat s uvedením autora a URL tohoto webu bez dalších omezení.