Dockerfile tohohle blogu vychází z image php:8.4.27-fpm-alpine a PHP v Herdu na mém stroji hlásí taky 8.4.27. To se hodí, protože 8.4.27 je první verze větve 8.4, která opravuje dvě kritické zranitelnosti oznámené 21. října 2026. Obě mají CVSS v4.0 9.2 a obě vedou ke vzdálenému spuštění kódu bez přihlášení. Skóre 10.0, které den před oznámením kolovalo na internetu, bylo chybné.
Co se opravuje
Opravy vyšly ve verzích 8.5.12, 8.4.27, 8.3.36 a 8.2.35. Zranitelné jsou i větve 7.4, 8.0 a 8.1. PHP pro ně zveřejnilo jen minimální opravy ve zdrojovém kódu, takže se podívej, co vydala tvoje distribuce. Distribuce opravu často zapracují do balíčku a číslo verze se přitom nezmění.
Chyba CVE-2026-109618 vzniká při nedostatku paměti. Když požadavek narazí na memory_limit ve špatnou chvíli, PHP nechá vnitřní data napůl inicializovaná a později je přečte jako platná. Datadog to rozebral na příkladu vkládání do hash tabulky: počítadla se zvýší dřív, než se alokuje klíč, a když alokace selže, zůstane v tabulce záznam, který nikdo nenaplnil. Úklid na konci požadavku ho považuje za hotovou hodnotu a podle zbylých dat, jejichž obsah útočník ovlivní, zavolá callback. V laboratoři Datadogu se útok dostal až k volání system().
Druhá chyba, CVE-2026-109619, je o stavu, který přežije svůj požadavek. Část dat, která worker drží mezi požadavky, ukazuje do paměti jednoho konkrétního požadavku. Když fatální chyba přeruší úklid, další požadavek na stejném workeru jde po ukazateli do uvolněné paměti (use-after-free). Chybu lze vyvolat mimo jiné přes session.upload_progress.enabled, které je ve výchozím nastavení zapnuté a běží i bez session_start(). Na PHP 8.5 k ní vede i fatal_error_backtraces.
Exploit jsem nezkoušel a zkoušet nebudu, vycházím z oznámení PHP Foundation a z rozboru Datadogu. U mod_php se první chyba projeví při zpracování požadavku, dřív než se spustí jediný řádek tvé aplikace. U PHP-FPM, na kterém běží i tenhle blog, PHP Foundation zneužití potvrdilo přes kód aplikace. Podle Datadogu přihlášení v aplikaci útok nezastaví, protože PHP požadavek zpracuje dřív než kód aplikace, takže na middleware v Laravelu se spoléhat nedá.
Útočníci byli napřed. AWS prý zachytilo pokusy o zneužití už 17. října, čtyři dny před vydáním. A tím padlo embargo: Calif, který nahlásil první chybu, omylem zveřejnil video s ukázkou zneužití a Chainguard vydal image s opravou víc než šest hodin před koordinovaným vydáním.
Co s tím
Spolehlivě pomůže jen aktualizace. Zmírnit jde pouze druhou chybu: nastav session.upload_progress.enabled=0 a u PHP 8.5 ještě fatal_error_backtraces=0, a to v php.ini, v souboru v conf.d (oficiální image žádný php.ini nenačítá) nebo v konfiguraci poolu PHP-FPM (ne přes ini_set(), ten přijde pozdě). Pak workery restartuj.
U kontejnerů přestav image a nasaď nové kontejnery. php -v na hostiteli o kontejneru nic neřekne. Verzi z oficiálního image ukáže až tohle:
docker exec <kontejner> php -v
A pro jistotu projdi logy. Podle Datadogu zanechává selhání při inicializaci požadavku řádek Allowed memory size ... exhausted s Unknown on line 0. Jednotlivý výskyt nic nedokazuje, několik výskytů za sebou už stojí za pozornost:
docker logs <kontejner> 2>&1 | grep 'Allowed memory size' | grep 'Unknown on line 0'