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!!!