Накратко: FrankenPHP е сървър за приложения на базата на Caddy, който вгражда PHP в собствената си програма. За сигурността на FrankenPHP след PHP2Shell това означава: от значение не са PHP пакетите на дистрибуцията, а версията на PHP във Binary или контейнерния Image на FrankenPHP. Изградете или изтеглете вариант с коригиран PHP и рестартирайте всички Worker.
Защо FrankenPHP се пачва по различен начин
При класическите конфигурации дистрибуцията доставя PHP като пакет, а актуализацията заменя файловете. FrankenPHP обаче съдържа PHP като вградена библиотека. Който ползва официалния Binary или изграден върху него контейнерен Image, получава PHP заедно с него. apt upgrade на хоста не променя нищо в това.
PHP2Shell обхваща CVE-2026-109618 и CVE-2026-109619, и двете с CVSS v4.0 9,2. Проектът PHP изрично посочва FrankenPHP сред засегнатите режими на работа. Коригирани са PHP 8.5.12, 8.4.27, 8.3.36 и 8.2.35. Решаващо е следователно срещу коя версия на PHP е изграден Вашият FrankenPHP.
Worker режим и PHP2Shell
FrankenPHP може да изпълнява приложения в Worker режим. При него приложението се зарежда веднъж и после обработва много заявки една след друга в същия процес. Това носи скорост, но удължава живота на всеки процес.
CVE-2026-109619 описва вътрешно състояние на заявка, което може да остане след освобождаване на паметта; по-късна заявка в същия Worker може да го използва, преди да е нулирано. В Worker режима взаимодействието на много заявки в един процес е нормалният случай. Това не е причина да се откажете от Worker режима, но е ясна причина актуализациите и рестартите да се правят особено грижливо. Технически подробности има в CVE-2026-109619.
Сигурност на FrankenPHP: проверка на версията
Проверете вградената версия на PHP директно в работещата система. Следващите команди само четат; имената на услугите и контейнерите са примери.
# Инсталиран Binary
frankenphp version
# В работещ контейнер (името на контейнера е пример)
docker exec app frankenphp version
docker exec app php -v
# Кой Image действително работи? (Digest показва точното състояние)
docker inspect --format '{{.Image}} {{.Config.Image}}' app
Отбележете версията на PHP от изхода. Ако е преди коригираните версии, системата е уязвима. Проверявайте винаги работещия контейнер, а не само последно изградения Image, защото новият Image действа едва след смяната на контейнерите.
Внесете актуализацията и рестартирайте всички Worker
Как изглежда актуализацията, зависи от Вашата инсталация:
- Binary на хоста: инсталирайте нова версия на FrankenPHP с коригирана версия на PHP, рестартирайте услугата.
- Контейнер: изтеглете базов Image с коригирана версия на PHP, изградете наново собствения Image без кеш за базовия слой, сменете контейнера.
- Компилиран самостоятелно: изградете наново срещу коригираната версия на PHP, създайте наново всички разширения със същата версия.
# Пример за инсталация на хоста като услуга на systemd
systemctl restart frankenphp
# Пример за Docker Compose: ново изграждане без кеш и смяна на контейнера
docker compose build --pull --no-cache
docker compose up -d --force-recreate
След това проверете отново версията на PHP в работещия контейнер и времето на стартиране на процесите. В Worker режима всеки Worker трябва да е рестартиран. При Kubernetes важат допълнителни стъпки, описани в Пач на PHP в Kubernetes, а за контейнерите като цяло в Пач на PHP в Docker контейнери.
Таг като latest или основна версия в името на Image не гарантира, че имате най-новото състояние. Изтеглете базовия Image активно наново и след това проверете версията на PHP в работещия контейнер.
Временни мерки и укрепване
Ако актуализацията не може да се направи веднага, php.net препоръчва временни мерки, които не осигуряват пълна защита. При FrankenPHP задавате стойностите в php.ini, който FrankenPHP зарежда, или чрез PHP настройките в конфигурацията на Caddy, не чрез ini_set() в приложението.
; php.ini в контейнера или на хоста
session.upload_progress.enabled = 0
post_max_size = 8M
upload_max_filesize = 6M
При функция за качване php.net посочва post_max_size = 32M. При PHP 8.5 се добавя fatal_error_backtraces=0. Ограничението на паметта се задава на ниво контейнер, например чрез лимита на паметта на контейнера, а не чрез RLIMIT_AS или RLIMIT_DATA. След всяка промяна рестартирайте всички Worker.
За постоянна експлоатация си струва да се препраща към Image с фиксиран Digest, да се изгражда редовно наново автоматично и във веригата за изграждане да се включи скенер на Image. Освен това пачът не премахва зловреден софтуер, внесен преди това. Запазете логовете от 20.10.2026 г. нататък; при контейнерите това означава да ги запазите, преди да ги смените.
Който ползва FrankenPHP като статично изграден Binary, трябва да знае, че там освен PHP са вградени трайно и всички разширения. Затова актуализацията винаги означава замяна на целия Binary. След смяната проверете версията и списъка със заредените разширения, дали всичко е налично както преди, и тествайте приложението, преди да изхвърлите старото състояние. В контейнерни среди се препоръчва всеки Image да се маркира с датата на изграждането. Така можете по всяко време да проследите кое състояние кога е работило и при съмнение целенасочено да се върнете назад, без отново да попаднете на уязвимо състояние. Записвайте съответствието между Image, версия на PHP и момент във Вашата документация.
Как помага PHP SOS конкретно?
- Проверяваме коя версия на PHP действително е във Вашите Binary на FrankenPHP и в работещите контейнери.
- Чрез услугата за PHP пач изграждаме Image наново, сменяме контейнерите и рестартираме всички Worker, с доказателство.
- Запазваме логовете преди смяната и проверяваме приложението за следи.
- За постоянна експлоатация настройваме автоматизирани наново изграждания и проверки на Image в рамките на укрепването на сървъри.
Често задавани въпроси
Помага ли актуализация с apt или dnf при FrankenPHP?
Само ако самият FrankenPHP идва от тези източници на пакети и е изграден срещу пачнатия PHP. Често PHP е вграден трайно във Binary на FrankenPHP или в контейнерния Image. Тогава трябва да актуализирате Binary или Image.
Защо Worker режимът е особено важен при PHP2Shell?
В Worker режима приложението остава в паметта и обработва много заявки последователно в един и същи процес. CVE-2026-109619 засяга точно вътрешно състояние, което може да остане между заявките в същия Worker. Затова рестартът на всички Worker след актуализацията е задължителен.
Как да проверя коя версия на PHP е вградена във FrankenPHP?
Binary на FrankenPHP извежда при извикване на версията вградената версия на PHP. В контейнер можете да изпълните командата чрез docker exec. Внимавайте да проверявате версията в действително работещия контейнер, а не в наскоро изградения Image.
Има ли за FrankenPHP собствени временни мерки?
Важат общите указания на php.net. Задавате стойностите в php.ini, който FrankenPHP зарежда, или в PHP конфигурацията на Caddy файла, не чрез ini_set() в приложението. След това рестартирайте всички Worker.