21 жовтня команда PHP випустила PHP 8.5.12, 8.4.27, 8.3.36 і 8.2.35. Вони закривають дві вразливості, що дозволяють виконати довільний код на сервері без автентифікації: CVE-2026-109618 і CVE-2026-109619, обидві з оцінкою 9.2 за CVSS v4.0. Під загрозою кожна інсталяція PHP, що обслуговує веб-запити: PHP-FPM, Apache з mod_php, php-cgi, FrankenPHP і LiteSpeed. Тобто практично кожен Laravel-застосунок у продакшені. Повного обхідного шляху немає - тільки оновлення.
Що саме зламано
Обидві вразливості сидять у ядрі PHP, а не у фреймворку чи вашому коді. За даними Laravel Forge, вони тягнуться ще з 2004 року, тож вразлива будь-яка версія, яку ви могли встановити.
- RCE через пошкодження при OOM (CVE-2026-109618). Коли PHP вичерпує пам'ять, він перериває обробку запиту в момент, коли частина внутрішніх даних ще не ініціалізована. Під час завершення запиту PHP сприймає ці неповні дані як коректні. Дійти до нестачі пам'яті, не виходячи за видимі ліміти, можна вже на етапі розбору multipart-запиту.
- RCE через застарілий глобальний стан (CVE-2026-109619). Воркер тримає глобальний стан, який вказує на пам'ять одного запиту. Якщо запит обірвався фатальною помилкою, нестачею пам'яті чи таймаутом, цей стан не скидається, і наступний запит у тому самому воркері встигає ним скористатися, перш ніж звичайна ініціалізація його перезапише. Класичний use after free.
Найвищий ризик команда PHP бачить у mod_php: там продемонстровано експлойт, який спрацьовує від неавтентифікованого запиту ще до того, як виконається бодай рядок коду застосунку. Для PHP-FPM повного експлойта першої вразливості не показали, але аналіз коду підтверджує, що він вразливий, а для другої є робочий сценарій, який залежить від поведінки застосунку. FrankenPHP, за оцінкою авторів advisory, поводиться як mod_php. Тож "у нас FPM, нас не стосується" - не аргумент.
Як оновитися
Цільові версії: 8.5.12, 8.4.27, 8.3.36 або 8.2.35. Якщо ви тестуєте PHP 8.6, виправлення є і в 8.6.0 RC4. Дистрибутиви й LTS-постачальники отримали патчі заздалегідь, тож оновлені пакети вже мають бути у вашому менеджері пакетів.
На Ubuntu з пакетами Ondřej Surý (саме їх ставить Forge) спершу перевірте, яку версію запропонує apt, а потім оновіть усі пакети потрібної версії PHP, не чіпаючи конфіги:
apt-cache policy php8.4-fpm
sudo apt-get install --only-upgrade -y \
-o Dpkg::Options::="--force-confold" \
$(dpkg -l 'php8.4*' | awk '/^ii/ {print $2}')
Якщо Candidate ще не збігається з виправленою версією, пакети до репозиторію не дійшли - зачекайте й повторіть.
Docker. Виправлення має пройти через офіційні образи Docker Hub і все, що на них збудовано. Перезберіть власні образи зі свіжим базовим (docker build --pull) і перевірте php -v уже всередині контейнера: старий шар у кеші збірки легко пропустити.
PHP 8.1 і старіші. Офіційно команда PHP їх більше не підтримує і нових випусків не публікувала. Але через серйозність ситуації вона підготувала мінімальні бекпорти вихідного коду для 7.4, 8.0 і 8.1, а Ondřej Surý випустив на їх основі нові ревізії пакетів (наприклад, 8.1.34-9, 1:8.0.30-25, 1:7.4.33-31). Пастка в тому, що php -v до і після оновлення показує ту саму версію, тож перевіряти треба ревізію пакета:
dpkg -l 'php8.1*' | awk '/^ii/ {print $2, $3}'
Це латка, а не рішення: наступної вразливості для цих версій може й не бути кому закрити. А PHP 8.2 завершує життєвий цикл 31 грудня 2026 року - час планувати перехід і з нього.
Якщо оновитися прямо зараз не можна
Команда PHP перелічила налаштування, які звужують окремі шляхи атаки. Вона ж прямо попереджає: жодне з них не робить сервер безпечним, це лише спосіб протриматися до оновлення.
memory_limit=-1, заданий так, щоб застосунок не міг його перевизначити (php_admin_value у пулі FPM чи конфігурації Apache). Прибирає керований збій ліміту пам'яті, але збій виділення на рівні системи все одно може дійти до вразливого коду.
- Низький
post_max_size: 8M для застосунків без завантаження файлів, 32M - якщо воно потрібне. upload_max_filesize має бути меншим.
- Ліміти на вебсервері чи проксі: розмір декодованого запиту, кількість полів, частин multipart, заголовків і глибина вкладеності, зокрема для запитів без коректного
Content-Length.
session.upload_progress.enabled=0 у php.ini, пулі FPM чи конфігурації сервера з перезапуском усіх воркерів. ini_set() і .user.ini спрацьовують занадто пізно.
- На PHP 8.5 -
fatal_error_backtraces=0, теж із перезапуском.
- Ліміт пам'яті контейнера чи cgroup як межа доступності. А от
RLIMIT_AS і RLIMIT_DATA не використовуйте: саме вони провокують вразливий збій виділення пам'яті.
Додатковий захист дали й WAF: Cloudflare, за даними Securing Laravel, автоматично ввімкнув правила для безкоштовних тарифів, а на платних їх треба вмикати вручну.
Два продовження
23 жовтня PHP опублікував інформаційне попередження про ще один, малоймовірний шлях до RCE (CVE-2026-115560). Він можливий, лише якщо застосунок у конфігурації ставить session.serialize_handler у php_binary або php_serialize, а під час виконання через ini_set() перемикає його на php перед session_start(), і при цьому session upload progress увімкнено. Laravel зазначає, що фреймворк так не робить. Рекомендація та сама: session.upload_progress.enabled=0 до наступного планового випуску. Якщо ви вимкнули його ще 21 жовтня - нічого робити не треба. На нових серверах Forge це налаштування тепер вимкнене за замовчуванням, на наявних - вирішувати вам.
26 жовтня вийшли перезібрані Windows-збірки 8.5.12-1, 8.4.27-1, 8.3.36-1 і 8.2.35-1 з Brotli 1.2.1. Вона виправляє CVE-2026-111497 - запис за межами буфера при декомпресії. У Windows-збірках до вразливого декодера можна дістатися через cURL з автоматичною розпаковкою HTTP-відповідей: за замовчуванням її вимкнено, але HTTP-клієнти можуть її вмикати. Версія PHP не змінюється, суфікс -1 позначає лише перезбирання із свіжими залежностями. Linux-серверів це не стосується.
Як це розгорталося
Вразливості знайшла компанія Calif під час аудиту PHP у програмі OpenAI Patch the Planet, а OpenAI і Wiz додали нові вектори з тим самим корінням. 20 жовтня PHP попередив про випуск, але скоординоване розкриття посипалося: хтось опублікував CVE з неправильною датою та оцінкою 10, випуск пересунули на день раніше, у мережу потрапило відео з демонстрацією атаки, а в соцмережах з'явилися згенеровані "PoC". Частина з них, як розповів Фолькер Душ в інтерв'ю Laravel News, працювала лише проти спеціально модифікованого контейнера. Chainguard опублікував виправлені образи більш ніж на шість годин раніше за скоординований час. Багато хто просто вимкнув сайти до виходу патчів: за даними Oh Dear, на піку 18,8% сайтів, які вони моніторять, лежали.
Чекліст для Laravel-проєкту
- Усі сервери.
php -v і php-fpm8.4 -v (з вашою версією) на кожному сервері, включно з версіями PHP, які сайти зараз не використовують. Для 8.1 і старіших - ревізія пакета, а не версія.
- Довгоживучі процеси. Оновлення пакета перезапускає FPM, але воркери черг, Horizon, Octane і Reverb далі працюють на старому бінарнику, доки їх не перезапустити:
php artisan queue:restart
php artisan horizon:terminate
php artisan octane:reload
- Docker і CI. Перезберіть образи з
--pull, оновіть версію PHP у CI, щоб тести й збірки не їхали на старому рантаймі.
- Laravel Cloud. Застосунки оновлено на місці, повторне розгортання не потрібне. Середовища на Node 20 не розгорнуться, поки ви не оберете новішу версію Node.js.
- Forge. Автоматичні оновлення безпеки Ubuntu PHP не чіпають. Відкрийте вкладку PHP на кожному сервері й натисніть Update PHP для кожної встановленої версії. Сервери на Ubuntu 20.04 і старіших оновлення не отримають - потрібен новий сервер.
- Vapor. Нативний рантайм на PHP 8.2+ - повторне розгортання, власний чи Docker-рантайм - нове розгортання. Для PHP 8.0 і 8.1 патча немає.
- Хостинг і shared. Напишіть провайдеру й попросіть назвати версію або ревізію пакета, а не просто "ми оновилися".
Якщо після цього лишився хоч один сервер, який не можна оновити сьогодні, - тимчасові заходи вище, моніторинг логів і план міграції. Але саме в такому порядку, а не замість оновлення.