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.
