PHP 8.5.12, 8.4.27, 8.3.36 і 8.2.35: критичні виправлення віддаленого виконання коду та як оновитися без сюрпризів з Docker
21 жовтня 2026 PHP закрив дві критичні вразливості RCE без автентифікації. Кого це стосується, як перевірити реальну версію веб-сервера та три пастки Docker, які ми пройшли.
21 жовтня 2026 року проєкт PHP випустив версії 8.5.12, 8.4.27, 8.3.36 і 8.2.35. За даними php.net, вони закривають дві критичні вразливості, що можуть дозволити віддалене виконання коду без автентифікації. Обидві оцінені в 9.2 за CVSS v4.0. Якщо ви обслуговуєте веб-запити через PHP, плануйте оновлення сьогодні.
Що виправлено
Бюлетень безпеки проєкту описує дві проблеми:
- CVE-2026-109618 (GHSA-w8hw-w9fx-j79w, «RCE via OOM corruption»): обробка нестачі пам'яті може перервати PHP, коли дані запиту ініціалізовані лише частково, і завершення запиту сприйме некоректні дані як коректні.
- CVE-2026-109619 (GHSA-6wmf-4rv5-p3rp, «RCE via stale global state»): стан, що належить запиту, може пережити звільнення своєї пам'яті, і наступний запит у тому самому воркері використає його до скидання.
Уражені всі версії нижче 8.2.35, 8.3.36, 8.4.27 та 8.5.12. Бюлетень називає оновлення єдиним повним виправленням.
Кого це стосується
Усього, що обслуговує веб-запити через PHP. Бюлетені GitHub розглядають Apache mod_php, PHP-FPM, LiteSpeed (LSAPI) і FrankenPHP. В анонсі на php.net сказано, що ризик найвищий для mod_php, «з продемонстрованим експлойтом, де запит без автентифікації запускає атаку ще до виконання будь-якого коду застосунку».
За бюлетенями, PHP-FPM виглядає вразливим за аналізом коду, а для другої вразливості підтверджено шлях через життєвий цикл сесії; для FrankenPHP аналіз вказує, що для першої вразливості він імовірно вразливий до атак, незалежних від застосунку. Деталі різняться залежно від SAPI, тож вважайте в зоні ризику всі веб-SAPI.
Зауваження щодо формулювань: php.net говорить про продемонстрований експлойт. Первинного джерела, яке б підтверджувало реальні атаки, ми не знайшли, тому не стверджуємо цього.
Версії та завершення підтримки
- Виправлено у 8.5.12, 8.4.27, 8.3.36, 8.2.35.
- PHP 8.2 завершує підтримку 31 грудня 2026.
- PHP 8.1 і старіші проєкт більше не оновлює. Бюлетень зазначає, що деякі вендори надають бекпорти.
- Трекер Debian на момент перевірки показує виправлення в bookworm (php8.2 8.2.35-1
deb12u1) і trixie (php8.4 8.4.27-1deb13u1).
Якщо оновитися одразу не можна
Бюлетень наводить часткові заходи, які не роблять систему безпечною:
memory_limit = -1 ; через php_admin_value, щоб не перевизначили
session.upload_progress.enabled = 0 ; потім перезапустіть воркери
; лише PHP 8.5:
fatal_error_backtraces = 0
Також радять зменшити post_max_size (8M без завантажень, 32M із завантаженнями), обмежити кількість multipart-частин, заголовків і завантажень або блокувати multipart-запити на фронтенді, якщо вони не потрібні.
Перевірте версію, яку справді виконує сервер
php -v показує версію CLI, а не обов'язково ту, що відповідає на HTTP-запити. Перевіряйте веб-SAPI:
# всередині контейнера або на хості, що обслуговує трафік
php -r 'echo PHP_VERSION, " ", PHP_SAPI, PHP_EOL;' # лише CLI, орієнтир
php-fpm -v # бінарник FPM
Надійна відповідь — запитати працюючий веб-процес: тимчасова сторінка, що виводить PHP_VERSION і PHP_SAPI (потім видаліть її, і ніколи не лишайте phpinfo() публічним).
Далі перезапустіть усі процеси PHP. Новий бінарник на диску нічого не змінює для вже запущених процесів. Довгоживучі воркери (Octane, RoadRunner, режим worker у FrankenPHP, воркери черг, планувальники) тримають старий код до перезапуску.
Що зробили ми у Woodander
Ми оновили власний стек того ж дня. Три речі забрали час, і вони стосуються більшості Docker-конфігурацій.
1. Образи відстають від релізу. Через кілька годин після релізу образ dunglas/frankenphp:1-php8.4-bookworm усе ще містив PHP 8.4.26, тоді як офіційний php:8.4-zts-bookworm уже мав 8.4.27. Ми зібрали власну базу: офіційний образ PHP ZTS і бінарник FrankenPHP, скопійований з upstream-образу (він динамічно лінкує libphp.so). Ми перевірили, що веб-SAPI віддає 8.4.27, і повернемося на upstream, коли його перезберуть. Зверніть увагу: frankenphp version досі показує версію PHP, з якою зібрано бінарник, тож перевіряйте реальним запитом, а не банером.
2. Реєстр пакетів був перевантажений. PECL повертав помилки 504, поки всі перезбирали образи, і наша збірка розширення redis впала. Архів тегу phpredis з GitHub — не повноцінна заміна: у ньому немає сабмодуля liblzf. Повторна спроба після відновлення PECL спрацювала. Кешуйте або вендорьте збірки розширень і тримайте перевірений образ для відкату.
3. ufw не захищає порти, опубліковані Docker. Правило ufw «дозволити лише Cloudflare» не діє на порти, які публікує Docker, бо правила iptables від Docker спрацьовують першими. Робіть обмеження в ланцюжку DOCKER-USER або використовуйте Cloudflare Tunnel, щоб origin не мав публічного порту. Перевірте ззовні:
curl -sS -m 5 -o /dev/null -w '%{http_code}\n' http://YOUR_ORIGIN_IP:PORT/
Якщо відповідь приходить, origin доступний напряму, що б не показував ufw. Це найважливіше саме під час оновлення.
Чекліст
- Зробіть знімок сервера або збережіть тег попереднього образу.
- Оновіться до виправленої версії своєї гілки (або до пакета вендора з бекпортом).
- Перезапустіть усе, що виконує PHP: FPM, Apache, FrankenPHP, воркери черг, планувальники.
- Перевірте версію для кожного процесу через веб-SAPI.
- Переконайтеся, що origin недоступний напряму, якщо ви покладаєтеся на CDN або фаєрвол.
- Перевірте ознаки компрометації: невідомі файли у веб-каталогах і каталогах завантажень, нові cron-завдання, незвичні процеси, неочікувані вихідні з'єднання, логи PHP зі збоями чи фатальними помилками. Бюлетень наголошує, що чисті логи не доводять безпеку.