# Как да обезопасите FrankenPHP

> FrankenPHP сигурност след PHP2Shell: проверка на вградената версия на PHP, ново изграждане на Binary или Image, рестарт на всички Worker и укрепване.

Източник: https://phpsos.de/bg/server/frankenphp/  
Актуалност: 25.10.2026  
Доставчик: PHP SOS, Спешна помощ за PHP и сигурност на сървъри. Незабавна помощ по WhatsApp: https://wa.me/491736494914?text=%D0%97%D0%B4%D1%80%D0%B0%D0%B2%D0%B5%D0%B9%D1%82%D0%B5%2C%20PHP%20SOS%2C%20%D0%B8%D0%BC%D0%B0%D0%BC%D0%B5%20%D0%BD%D1%83%D0%B6%D0%B4%D0%B0%20%D0%BE%D1%82%20%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%20%D1%81%20%D0%BD%D0%B0%D1%88%D0%B8%D1%8F%20PHP%20%D1%81%D1%8A%D1%80%D0%B2%D1%8A%D1%80.%20%D0%A4%D0%B8%D1%80%D0%BC%D0%B0%3A%20%E2%80%A6%20%D0%A3%D0%B5%D0%B1%D1%81%D0%B0%D0%B9%D1%82%3A%20%E2%80%A6

**Накратко:** 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](https://phpsos.de/bg/php2shell/cve-2026-109619/).

## Сигурност на FrankenPHP: проверка на версията

Проверете вградената версия на PHP директно в работещата система. Следващите команди само четат; имената на услугите и контейнерите са примери.

```bash
# Инсталиран 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, създайте наново всички разширения със същата версия.

```bash
# Пример за инсталация на хоста като услуга на systemd
systemctl restart frankenphp

# Пример за Docker Compose: ново изграждане без кеш и смяна на контейнера
docker compose build --pull --no-cache
docker compose up -d --force-recreate
```

След това проверете отново версията на PHP в работещия контейнер и времето на стартиране на процесите. В Worker режима всеки Worker трябва да е рестартиран. При Kubernetes важат допълнителни стъпки, описани в [Пач на PHP в Kubernetes](https://phpsos.de/bg/server/kubernetes/), а за контейнерите като цяло в [Пач на PHP в Docker контейнери](https://phpsos.de/bg/php2shell/docker-container-patchen/).

> **Важно:**
> Таг като `latest` или основна версия в името на Image не гарантира, че имате най-новото състояние. Изтеглете базовия Image активно наново и след това проверете версията на PHP в работещия контейнер.

## Временни мерки и укрепване

Ако актуализацията не може да се направи веднага, php.net препоръчва временни мерки, които не осигуряват пълна защита. При FrankenPHP задавате стойностите в php.ini, който FrankenPHP зарежда, или чрез PHP настройките в конфигурацията на Caddy, не чрез `ini_set()` в приложението.

```ini
; 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 пач](https://phpsos.de/bg/leistungen/php-patch-service/) изграждаме Image наново, сменяме контейнерите и рестартираме всички Worker, с доказателство.
- Запазваме логовете преди смяната и проверяваме приложението за следи.
- За постоянна експлоатация настройваме автоматизирани наново изграждания и проверки на Image в рамките на [укрепването на сървъри](https://phpsos.de/bg/leistungen/server-haertung/).


## Често задавани въпроси

**Помага ли актуализация с 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.

## Източници

- [php.net: Съобщения за сигурност](https://www.php.net/)
- [PHP 8 ChangeLog](https://www.php.net/ChangeLog-8.php)
- [OWASP Cheat Sheets](https://cheatsheetseries.owasp.org/)
