PHP2Shell: перевірка та патч RCE-вразливостей PHP на сервері
21 жовтня 2026 року проєкт PHP випустив 8.5.12, 8.4.27, 8.3.36 і 8.2.35, щоб закрити дві вразливості в самому PHP, які отримали назву PHP2Shell. Обидві дозволяють запиту від користувача, який не увійшов у систему, виконати код від імені воркера PHP. Помилка в середовищі виконання, а не у WordPress, Drupal чи Joomla, тому оновлення CMS або її плагінів її не закриває. У цьому посібнику: кого це стосується, як перевірити сервер однією командою, що зробити вже сьогодні, якщо оновитися поки не можна, і як оновитися безпечно.
Що це за дві вразливості
- CVE-2026-109618, пошкодження пам'яті при її нестачі - коли виділити пам'ять не вдається, PHP може обірвати запит, поки його внутрішні дані налаштовані лише наполовину, а подальше очищення довіряє цим зламаним даним. Спеціально сформований multipart-запит може це спровокувати навіть у межах ваших лімітів розміру.
- CVE-2026-109619, застарілий глобальний стан - стан, що належить одному запиту, може пережити пам'ять, яка за ним стоїть. Наступний запит, який обслуговує той самий воркер, може використати цю звільнену пам'ять до того, як її скинуто (use-after-free). Підтверджений шлях проходить через функцію session upload progress і фатальні помилки.
Обидві мають оцінку 9.2 (critical) за CVSS 4.0. В анонсі PHP сказано, що під час дослідження було створено робочий експлойт і що ризик найвищий для Apache з mod_php, де атака виконується ще до будь-якого коду застосунку. За кілька днів з'явилося кілька публічних proof-of-concept експлойтів; Rapid7 повідомляє, що кожен працює лише для однієї комбінації ОС, версії PHP та вебсервера, і фіксує спроби експлуатації. Ставтеся до цього як до термінового патча.
Кого це стосується
Кожну інсталяцію PHP, що обслуговує вебзапити: PHP-FPM, Apache з mod_php, php-cgi, FrankenPHP і LiteSpeed. Це майже кожен сервер з WordPress, WooCommerce, Drupal, Joomla, Magento, Laravel і Nextcloud.
| Гілка PHP | Вразливі версії | Перша виправлена версія |
|---|---|---|
| 8.5 | 8.5.0 - 8.5.11 | 8.5.12 |
| 8.4 | 8.4.0 - 8.4.26 | 8.4.27 |
| 8.3 | 8.3.0 - 8.3.35 | 8.3.36 |
| 8.2 | 8.2.0 - 8.2.34 | 8.2.35 |
| 7.4, 8.0, 8.1 | усі | релізу на php.net немає; бекпорти у вихідному коді, пакети дистрибутива або LTS-вендора |
| 7.3 і старші | усі | виправлення немає |
Дистрибутиви часто залишають старий номер версії й переносять виправлення (наприклад, пакет Debian або Ubuntu, що досі показує 8.2.x), тому для PHP з пакетів перевіряйте пакет у security tracker свого дистрибутива, а не лише номер.
Перевірка сервера однією командою
Збережіть це як php2shell-check.php і запустіть тим самим PHP, що обслуговує ваш сайт. Скрипт виводить версію, чи вона старша за виправлення, і два параметри, які змінюють тимчасові заходи нижче.
<?php
// PHP2Shell check: is this PHP build older than the October 21, 2026 fixes?
$fixed = ['8.5' => '8.5.12', '8.4' => '8.4.27', '8.3' => '8.3.36', '8.2' => '8.2.35'];
$branch = PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION;
echo "PHP " . PHP_VERSION . " (" . PHP_SAPI . ")\n";
if (!isset($fixed[$branch])) {
echo "Branch $branch gets no php.net release: check your distro or LTS vendor, or upgrade to 8.4.\n";
} elseif (version_compare(PHP_VERSION, $fixed[$branch], '<')) {
echo "VULNERABLE: upgrade to {$fixed[$branch]} or later (or a distro build with the backport).\n";
} else {
echo "Patched upstream version ({$fixed[$branch]}+).\n";
}
echo "session.upload_progress.enabled = " . (ini_get('session.upload_progress.enabled') ? 'On' : 'Off') . "\n";
echo "post_max_size = " . ini_get('post_max_size') . ", memory_limit = " . ini_get('memory_limit') . "\n";
php php2shell-check.php
Вивід перевірено 2026-10-24 в офіційних Docker-образах php:
PHP 8.3.30 (cli)
VULNERABLE: upgrade to 8.3.36 or later (or a distro build with the backport).
session.upload_progress.enabled = On
post_max_size = 8M, memory_limit = 128M
PHP 8.4.27 (cli)
Patched upstream version (8.4.27+).
PHP 7.2.34 (cli)
Branch 7.2 gets no php.net release: check your distro or LTS vendor, or upgrade to 8.4.
php у командному рядку може бути іншою збіркою, ніж та, що стоїть за сайтом. Щоб перевірити вебчастину, виконайте php-fpm -v (або php-fpm8.3 -v у Debian і Ubuntu), або покладіть скрипт у корінь сайту на один запит і одразу після цього видаліть.
Якщо оновитися сьогодні не можна: тимчасові заходи
Команда PHP прямо каже, що повного захисту без оновлення немає і єдиний безпечний вибір - оновитися. Ці налаштування звужують атаку, поки ви плануєте оновлення. Задайте їх там, де застосунок не може їх перевизначити - у php.ini або в пулі FPM через php_admin_value, - бо ini_set() і .user.ini спрацьовують надто пізно. Потім перезапустіть усі воркери.
; FPM pool, e.g. /etc/php/8.3/fpm/pool.d/zz-php2shell.conf (the [www] section of your pool)
[www]
php_admin_value[session.upload_progress.enabled] = 0
php_admin_value[post_max_size] = 32M
php_admin_value[upload_max_filesize] = 30M
php-fpm8.3 -t && systemctl restart php8.3-fpm
Ми перевірили цей файл пулу командою php-fpm -t на PHP 8.4 (configuration test successful). Що робить кожен рядок:
session.upload_progress.enabled = 0блокує підтверджений шлях CVE-2026-109619, але не кожен варіант. Вимкніть його, якщо від нього не залежить індикатор прогресу завантаження.post_max_size8M, якщо завантажень немає, або 32M, якщо сайт приймає файли, іupload_max_filesizeнижче нього, як радить команда PHP. Також обмежте розмір запиту в nginx (client_max_body_size 32m;) або Apache (LimitRequestBody).- Лише на PHP 8.5 додайте
fatal_error_backtraces = 0. - PHP також пропонує
memory_limit = -1, заданий адміністратором, щоб сам ліміт пам'яті не можна було використати для запуску CVE-2026-109618. Робіть це лише з лімітом пам'яті контейнера або cgroup навколо PHP, інакше один поганий запит може забрати всю RAM сервера. Не використовуйте для цьогоRLIMIT_ASчиRLIMIT_DATA: вони можуть спровокувати вразливість.
Приховування помилок (display_errors, error_reporting, @) не допомагає, а порожній журнал помилок не доводить, що сервер не атакували.
Як оновитися
- PHP з пакетів (Debian, Ubuntu, RHEL, AlmaLinux). Встановіть оновлення безпеки (
apt update && apt upgradeабоdnf upgrade 'php*'), потім перезапустіть PHP-FPM або Apache, бо запущені воркери тримають старий код. Переконайтеся, що changelog пакета згадує CVE-2026-109618. - Docker-образи. Перезберіть на виправленому тегу (
php:8.4-fpmзараз відповідає 8.4.27) командоюdocker compose build --pull, потім перестворіть контейнери. Запущений контейнер тримає старий PHP, доки його не замінять. - PHP 7.4 - 8.1. Використайте пакет з бекпортом від вашого вендора або перейдіть на 8.4. PHP 7.3 і старші не отримають виправлення ніколи: сховайте сайт за allow-list або VPN, доки його не мігровано.
- Після оновлення знову запустіть скрипт перевірки й перегляньте журнал вебсервера на незвичні multipart POST-запити та падіння воркерів PHP з 21 жовтня.
Якщо потрібна допомога, кероване адміністрування серверів охоплює такі патчі, а наш посібник про хмарний сервер для WordPress показує налаштування PHP-FPM, де ці параметри зберігаються в пулі. Перед оновленням робочого сайту зробіть знімок: резервне копіювання та відновлення VM пояснює, як.
Що зробили ми
Того ж тижня ми перевірили кожен сервіс DCXV, що працює на PHP, і застосували заходи з цього посібника. Сервери клієнтів адмініструють їхні власники: якщо у вас PHP на хмарному або виділеному сервері DCXV, запустіть перевірку вище сьогодні. Новий хмарний сервер отримує актуальні пакети під час першого apt upgrade.
Джерела (перевірено 2026-10-24): анонс security-релізу PHP 8.x від 21 жовтня 2026 року, бюлетені PHP GHSA-w8hw-w9fx-j79w і GHSA-6wmf-4rv5-p3rp та аналіз Rapid7.
