Čo sa stalo
FrankenPHP je moderný aplikačný server pre PHP postavený na webovom serveri Caddy. Často sa nasadzuje ako hotový Docker obraz dunglas/frankenphp, napríklad pri aplikáciách na Symfony alebo Laravel. Správcovia projektu 5. februára 2026 zverejnili na GitHube bezpečnostné upozornenie GHSA-x9p2-77v6-6vhf a označili ho ako kritické.
Problém nie je v samotnom kóde FrankenPHP, ale v tom, ako sa jeho Docker obrazy zostavovali. Obrazy sa prestavovali len vtedy, keď vznikol nový tag základného obrazu. Alpine Linux, PHP a Go však bezpečnostné opravy zvyčajne vydávajú pod existujúcim tagom, takže obrazy FrankenPHP zostávali na starších, zraniteľných knižniciach. Výrobca ako príklad uvádza chybu CVE-2025-15467 v knižnici libcrypto3, ktorá umožňuje vzdialené spustenie kódu.
Spoločnosť VulnCheck chybu 12. novembra 2026 zaevidovala pod číslom CVE-2026-128027 a americká databáza NVD ju zverejnila 13. novembra 2026. Európska databáza EUVD ju vedie ako EUVD-2026-125075. Chyba nie je v katalógu CISA KEV, EUVD nezaznamenáva jej zneužitie a výrobca o útokoch nehovorí. Chybu nahlásil a opravil Tim Nelles.
Prečo je to nebezpečné
Ide o závislosť od zraniteľného komponentu tretej strany. VulnCheck ju označuje ako CWE-1395. Predstavte si stavebnú firmu, ktorá do domov montuje zámky od dodávateľa. Dodávateľ chybný zámok potichu vymení za opravený, no pod rovnakým katalógovým číslom. Firma sleduje len číslo, a tak ďalej montuje staré zámky zo skladu. Presne takto sa do obrazov FrankenPHP nedostali opravy z Alpine, PHP a Go.
Podľa VulnCheck mohli útočníci na diaľku zneužiť známe chyby v zastaraných systémových knižniciach a spustiť na serveri vlastný kód. Výrobca je opatrnejší: píše, že používatelia mohli prevádzkovať prostredie so známymi zraniteľnosťami, a to aj vtedy, keď mali najnovšiu podobu svojho tagu. V praxi zneužiteľnosť konkrétnej chyby v knižnici závisí aj od toho, ako ju aplikácia používa.
Ak by útok uspel, útočník by ovládol kontajner s aplikáciou. Mohol by čítať databázu, heslá a API kľúče z premenných prostredia, meniť web alebo sa pokúsiť dostať k ďalším systémom v sieti. Či by prenikol aj na samotný hostiteľský server, závisí od nastavenia kontajnera.
Skóre CVSS vyjadruje závažnosť chyby na stupnici 0 až 10. VulnCheck, ktorá CVE pridelila, dáva podľa CVSS 3.1 hodnotu 9,8, rovnako ako upozornenie FrankenPHP: útok ide cez sieť, je jednoduchý a nevyžaduje prihlásenie ani akciu používateľa. Podľa novšej verzie CVSS 4.0 ju VulnCheck hodnotí na 9,3. Skóre EPSS, ktoré odhaduje pravdepodobnosť zneužitia v najbližších 30 dňoch, je 0,86 %, čo je viac ako pri zhruba 59 % hodnotených chýb. Katalóg CISA KEV, zoznam preukázateľne zneužívaných chýb, ju neobsahuje.
Koho sa to týka
Týka sa to oficiálnych Docker obrazov dunglas/frankenphp vo verziách pred 1.1.11 a vlastných obrazov, ktoré sú na nich postavené, teda tých, ktoré majú v súbore Dockerfile riadok FROM dunglas/frankenphp. Výrobca upozorňuje, že ohrozený mohol byť aj ten, kto používal najnovšiu podobu konkrétneho tagu.
Typicky ide o tieto prostredia:
- firemné webové aplikácie a e-shopy na PHP bežiace v Dockeri alebo Kubernetes
- aplikácie na Symfony alebo Laravel nasadené v kontajneroch s FrankenPHP
- vývojové a testovacie servery dostupné z internetu
- CI/CD pipeline, ktoré z obrazu FrankenPHP stavajú vlastné obrazy
Netýka sa to klasických inštalácií PHP s Apache alebo PHP-FPM bez FrankenPHP. Upozornenie výrobcu hovorí o Docker obrazoch, iné spôsoby inštalácie FrankenPHP v ňom nespomína.
Ako zistiť, či ste zasiahnutí
Nasledujúce príkazy len čítajú informácie a nič nemenia. Najprv zistite, ktoré kontajnery bežia z obrazu FrankenPHP:
docker ps --format '{{.Names}} {{.Image}}' | grep -i frankenphp
Vlastné obrazy majú vlastný názov, takže ich tento príkaz nenájde. Verziu FrankenPHP vo všetkých bežiacich kontajneroch vypíše:
docker ps --format '{{.Names}}' | while read c; do v=$(docker exec "$c" frankenphp version 2>/dev/null) && echo "$c: $v"; done
Verzia nižšia ako 1.1.11 znamená, že ste zasiahnutí. Pri obrazoch na Alpine skontrolujte aj verziu systému a knižnice libcrypto3. Namiesto nazov-kontajnera doplňte meno kontajnera. Výrobca uvádza, že opravy priniesli Alpine 3.20.9, 3.21.6, 3.22.3 a 3.23.3. Nižšie vydanie v rovnakom rade je podozrivé.
docker exec nazov-kontajnera cat /etc/alpine-release
docker exec nazov-kontajnera apk list --installed libcrypto3
Obraz zostavený pred 4. februárom 2026, keď výrobca zmenil spôsob zostavovania, mohol obsahovať staré knižnice. Prvý príkaz vypíše dátum zostavenia všetkých obrazov na serveri. Druhý spustite v adresári s projektmi, nájde zmienky o FrankenPHP v súboroch Dockerfile a Compose.
docker image ls --format '{{.Repository}}:{{.Tag}} {{.CreatedAt}}'
grep -rni frankenphp --include='Dockerfile*' --include='*compose*.yml' --include='*compose*.yaml' .
Ako to opraviť
Opravená verzia je 1.1.11. Od 4. februára 2026 výrobca každý deň porovnáva základné obrazy so zdrojovými registrami a pri akejkoľvek zmene obrazy FrankenPHP automaticky prestaví. K vám sa však oprava nedostane sama. Obraz treba stiahnuť znova a kontajnery znova vytvoriť.
Postupujte takto:
- Spíšte všetky servery, projekty a CI pipeline, ktoré používajú FrankenPHP.
- Ak používate tag starší ako 1.1.11, zmeňte ho na 1.1.11 alebo novší.
- Stiahnite aktuálnu podobu svojho tagu, napríklad
docker pull dunglas/frankenphp:latest. - Ak staviate vlastný obraz, prestavajte ho s prepínačom
--pull, aby Docker stiahol čerstvé základné vrstvy. - Kontajnery znova vytvorte. Samotné stiahnutie obrazu bežiaci kontajner nezmení.
- Príkazmi z časti o kontrole overte, že beží nová verzia.
docker pull dunglas/frankenphp:latest
docker build --pull -t my-app .
Pri Docker Compose stačí v adresári projektu:
docker compose pull --ignore-buildable
docker compose build --pull
docker compose up -d
Ako dočasné riešenie výrobca uvádza práve vynútené stiahnutie čerstvých základných vrstiev cez --pull, iné opatrenia nespomína. Začnite systémami dostupnými z internetu, potom pokračujte internými a nakoniec vývojovými prostrediami.
Do budúcna nastavte pravidelné prestavovanie vlastných obrazov, napríklad raz týždenne, a ich kontrolu skenerom zraniteľností, napríklad Trivy alebo Grype. Zachytíte tak podobné problémy aj v iných obrazoch.
Čo ak už ste mohli byť napadnutí
Výrobca ani VulnCheck nezverejnili konkrétne indikátory napadnutia. Ak bežal zraniteľný kontajner dlhší čas dostupný z internetu, urobte základnú kontrolu ešte pred jeho zrušením, kým sú stopy na mieste. Nasledujúce príkazy len čítajú:
- Logy zobrazí
docker logs nazov-kontajnera. Hľadajte nezvyčajné chyby, pády procesu a neznáme požiadavky. - Príkaz
docker diff nazov-kontajneraukáže súbory, ktoré pribudli alebo sa zmenili oproti obrazu. Podozrivé sú nové PHP súbory vo webovom adresári a spustiteľné súbory v/tmp. - Príkaz
docker top nazov-kontajneravypíše procesy. Okrem FrankenPHP a vašej aplikácie by tam nemalo byť nič. - V aplikácii a databáze hľadajte neznáme administrátorské účty a nedávne zmeny oprávnení.
- Na firewalle skontrolujte nečakané odchádzajúce spojenia zo servera.
Ak nájdete niečo podozrivé, nestačí len vymeniť kontajner. Zmeňte heslá k databáze, API kľúče a ďalšie tajomstvá, ku ktorým mal kontajner prístup. Prizvite odborníka na bezpečnostné incidenty, najmä ak mal kontajner pripojený Docker socket alebo adresáre hostiteľa, prípadne bežal s rozšírenými oprávneniami. Vtedy sa útočník mohol dostať aj na samotný server.