---
title: 'PHP2Shell: критический RCE во всём PHP | DevSense'
description: 'Разбор PHP2Shell — CVE-2026-109618 и CVE-2026-109619, неаутентифицированного RCE в ядре PHP: как устроены уязвимости, чем они опасны, кто бросился чинить и как защитить свой сервер. Без рабочего эксплойта, в образовательных целях.'
faq:
    - { question: 'Что такое PHP2Shell и какие версии PHP затронуты?', answer: 'PHP2Shell — общее имя двух уязвимостей ядра PHP, CVE-2026-109618 и CVE-2026-109619, раскрытых 21 октября 2026 года. Вместе они дают неаутентифицированное удалённое выполнение кода через обычный разбор HTTP-запроса. Затронуты практически все ветки за последнее десятилетие; исправления вышли в PHP 8.5.12, 8.4.27, 8.3.36 и 8.2.35, для 8.1/8.0/7.4 PHP выпустил минимальные бэкпорты.' }
    - { question: 'Нужна ли атакующему авторизация или уязвимый плагин?', answer: 'Нет. В этом и суть: дыра в самом ядре PHP, на пути разбора входящего запроса, который выполняется ещё до кода приложения. Не нужны ни логин, ни конкретная CMS, ни уязвимый плагин — достаточно, чтобы сервер принимал HTTP-запросы и крутил PHP. Поэтому исследователи и говорят про «70% веба»: это доля сайтов на PHP, а не число реально взломанных серверов.' }
    - { question: 'Эксплуатируется ли уязвимость в реальных атаках?', answer: 'На момент написания (третий день после раскрытия) публично подтверждённых взломов именно через PHP2Shell нет, но Cloudflare и другие уже наблюдают сканирование и попытки эксплуатации, причём с мутацией полезной нагрузки для обхода фильтров. При неаутентифицированном RCE с CVSS до 9.2 окно между «обновить никто не успел» и «появились массовые атаки» измеряется днями.' }
    - { question: 'Что делать прямо сейчас, если обновиться немедленно нельзя?', answer: 'Обновление PHP — единственное полное решение. Пока оно не раскатано: включите WAF (Cloudflare, Fastly, Akamai, Imperva и облачные провайдеры уже выкатили защиту по умолчанию), ограничьте размер тела запроса на обратном прокси, отключите session.upload_progress.enabled и на PHP 8.5 fatal_error_backtraces, следите в логах за ошибками нехватки памяти с «Unknown on line 0» и падениями воркеров. Это снижает риск, но не закрывает дыру.' }
published: '2026-10-23'
---
# PHP2Shell: критический RCE во всём PHP — что случилось и как защититься

Есть особый сорт уязвимостей — те, что живут не в чьём-то плагине и не в кривой строке конкретного приложения, а в самом фундаменте, на котором стоит всё остальное. PHP2Shell — ровно такая. Это не дыра в WordPress, не промах одного разработчика и не забытый `eval()`. Это трещина в несущей стене: в том самом коде ядра PHP, который разбирает входящий запрос ещё до того, как выполнится первая строка вашего приложения.

21 октября 2026 года PHP выпустил экстренные релизы и раскрыл две уязвимости — **CVE-2026-109618** и **CVE-2026-109619**, — которые вместе дают то, страшнее чего в вебе почти ничего нет: **неаутентифицированное удалённое выполнение кода**. Без логина. Без уязвимого плагина. Без единого клика жертвы. Эта статья написана на третий день после раскрытия, когда патч уже есть, но половина интернета ещё не обновилась, — и поэтому написана без единой строчки рабочего эксплойта. Мы разберём, что сломалось и почему это так опасно, но не дадим в руки оружие. Цель — чтобы вы поняли врага и закрыли дверь, а не чтобы кто-то собрал атаку по нашему тексту.

**Связанные материалы:** [Веб-атаки и защита от них](web-attacks-and-prevention) · [Отказоустойчивые интеграции](resilient-external-integrations) · [Наблюдаемость и мониторинг](observability-monitoring-laravel) · [Zero-downtime deployment](zero-downtime-deployment-laravel)

## Содержание

* [Коротко: что нужно знать за тридцать секунд](#tldr)
* [Почему уязвимость в ядре — это другой масштаб](#why-core)
* [Таймлайн: как ИИ нашёл дыру во всём PHP](#timeline)
* [Две двери: что скрывается за двумя CVE](#two-doors)
* [Насколько серьёзен ущерб](#impact)
* [Взгляд атакующего: модель угроз без инструкции](#attacker)
* [Кто уже бросился чинить](#responders)
* [Есть ли уже пострадавшие](#victims)
* [Как защититься: по шагам](#defense)
* [Как увидеть атаку в своих логах](#detection)
* [PHP жив — и это доказательство](#php-alive)
* [Чеклист](#checklist)
* [Квиз для самопроверки](#self-test-quiz)

---

<a id="tldr"></a>
## Коротко: что нужно знать за тридцать секунд

* **Что:** две уязвимости ядра PHP под общим именем PHP2Shell — CVE-2026-109618 и CVE-2026-109619.
* **Чем грозит:** неаутентифицированное удалённое выполнение кода (RCE), тяжесть до **CVSS 9.2**.
* **Кого задевает:** практически все ветки PHP за последнее десятилетие, вне зависимости от CMS и фреймворка.
* **Где починено:** PHP **8.5.12, 8.4.27, 8.3.36, 8.2.35**; для 8.1/8.0/7.4 — минимальные бэкпорты от команды PHP.
* **Что делать:** обновить PHP и перезапустить PHP-FPM и воркеры очередей. Немедленно. Остальное — только временные подпорки.

Если вы читаете это с продакшена на непропатченной версии — закройте статью, обновитесь, вернитесь. Серьёзно.

---

<a id="why-core"></a>
## Почему уязвимость в ядре — это другой масштаб

Большинство веб-уязвимостей похожи на незапертое окно в одной конкретной квартире: баг в плагине, SQL-инъекция в самописном контроллере, забытая проверка прав. Чините квартиру — окно закрыто. PHP2Shell — это заводской брак в замке, который стоит на каждой второй двери планеты.

PHP обрабатывает входящий запрос слоями. Сначала — ядро: оно читает заголовки, разбирает тело запроса, наполняет суперглобальные массивы `$_POST`, `$_FILES`, `$_COOKIE`. И только потом управление доходит до вашего кода — до роутера Laravel, до ядра WordPress, до первой строчки, которую написали вы. PHP2Shell живёт **на первом слое**. Уязвимый путь выполняется у всех и всегда, просто потому что сервер принял запрос.

Отсюда и знаменитая формулировка исследователей про «70% интернета». Важно понимать, что это значит: PHP обслуживает порядка 70% всех сайтов в мире, и теоретическая поверхность атаки — это они все. Это **не** значит, что 70% сайтов уже взломаны или что каждый из них гарантированно пробивается в один запрос. Это значит, что потолок у этой уязвимости — размером с веб.

---

<a id="timeline"></a>
## Таймлайн: как ИИ нашёл дыру во всём PHP

У этой истории есть деталь, из-за которой она войдёт в учебники, — и это не сама уязвимость. Её нашли не классическим ручным аудитом, а связкой человека и ИИ. Исследователи Wiz вели поиск с помощью современных моделей, и, по их собственным словам, модель внесла «неоценимый вклад» не только в обнаружение, но и в превращение находок в рабочие эксплойты против нескольких целей — «за часы». Мы живём в мире, где фаззинг ядра PHP ведёт не только человек с отладчиком, но и ИИ, и обе стороны баррикад это уже поняли.

Хронология 2026 года (по данным Wiz):

| Дата | Событие |
|------|---------|
| 19 августа | Найдена первая из уязвимостей |
| 20 августа | Подтверждён неаутентифицированный RCE против Drupal |
| 21 августа | Подтверждён неаутентифицированный RCE против WordPress |
| 24 августа | Передано команде безопасности PHP |
| 21 сентября | PHP подтвердил проблему и начал скоординированное исправление |
| 21 октября | Выпущены патчи и состоялось публичное раскрытие |

Почти два месяца — между тихой передачей команде PHP и публичным раскрытием. Это и есть правильный, «взрослый» процесс: сначала чинят, потом рассказывают. Статья, которую вы читаете, появилась через два дня после последней строки этой таблицы.

---

<a id="two-doors"></a>
## Две двери: что скрывается за двумя CVE

Под именем PHP2Shell прячутся два разных дефекта — две двери в одну и ту же комнату. Разные исследователи и вендоры описывают лежащие в основе баги с небольшими расхождениями в деталях, и под каждым CVE скрывается скорее класс проблем, чем одна строчка. Мы намеренно остаёмся на уровне механики — «что именно сломалось», — не спускаясь до рецепта раскрутки до шелла.

### CVE-2026-109618 — обработка входящих данных запроса

Первая дверь открывается на этапе, когда PHP разбирает тело POST-запроса и обработку загрузок. Проблема — в работе с памятью на этом пути: при определённой форме входных данных ядро обращается к памяти, которую уже освободило, или нарушает учёт при её выделении. Там, где должна быть аккуратная «выделил — использовал — освободил», возникает окно, в котором состояние памяти перестаёт соответствовать ожиданиям кода. А нарушенная работа с памятью в нативном коде — это классический трамплин: от неё идёт путь и к утечке кусочков памяти процесса (а значит, к обходу защит вроде ASLR), и к контролю над исполнением.

Ключевая деталь: этот путь не требует ни авторизации, ни специальной конфигурации приложения. Достаточно, чтобы PHP автоматически разбирал тело запроса, — а он делает это всегда.

### CVE-2026-109619 — остаточное состояние между запросами

Вторая дверь тоньше и в каком-то смысле изящнее. PHP-FPM — это долгоживущий процесс: один и тот же воркер обслуживает запрос за запросом, не перезагружая фреймворк (почему это и быстро, и опасно, мы разбирали в статье про [очереди в продакшене](laravel-queues-production#memory)). Если после обработки одного запроса в воркере остаётся «мусорное» состояние — например, от механизма отслеживания прогресса загрузки файлов (`session.upload_progress`) или от формирования трассировок фатальных ошибок, — то следующий запрос может наткнуться на эти протухшие данные. Один запрос подготавливает ловушку, второй в неё попадает.

Коварство в том, что часть этих механизмов работает, даже если приложение никогда явно их не вызывало. `session.upload_progress` включён по умолчанию и срабатывает без единого `session_start()` в вашем коде.

> [!NOTE]
> Запомните две настройки из второй двери — `session.upload_progress.enabled` и (на PHP 8.5) `fatal_error_backtraces`. Ниже, в разделе о защите, именно их мы и будем прикрывать, если обновиться прямо сейчас нельзя.

---

<a id="impact"></a>
## Насколько серьёзен ущерб

RCE — это вершина пищевой цепи уязвимостей. Не «утекли данные», не «подменили страницу», а **чужой код выполняется на вашем сервере с правами вашего веб-процесса**. Что это означает на практике:

* **Полный контроль над приложением.** Атакующий читает и меняет что угодно в коде и файлах, доступных `www-data`.
* **Доступ к секретам.** `.env` с паролём от базы, ключи платёжных систем, токены API, `APP_KEY` — всё, что процесс может прочитать, читает и атакующий.
* **База данных целиком.** Не через хитрую инъекцию, а напрямую — с теми же учётными данными, что и приложение.
* **Боковое перемещение.** Сервер становится плацдармом: отсюда сканируют внутреннюю сеть, атакуют соседние сервисы, закрепляются через веб-шелл.
* **Тишина.** Успешная эксплуатация может вернуть обычный HTTP 200 и не уронить воркер. Снаружи — ничего, внутри — чужой уже дома.

Для сайта вроде DevSense, где нет платежей и персональных данных пользователей сверх минимума, прямой ущерб меньше, чем для интернет-магазина или банка. Но «меньше» не значит «нет»: даже наш сервер — это доступ к БД, к почтовым ключам, к инфраструктуре деплоя и отличный плацдарм для атак на других. Поэтому [мы обновили PHP](../tools/dockerfile-php-best-practices) в тот же день.

---

<a id="attacker"></a>
## Взгляд атакующего: модель угроз без инструкции

Посмотреть на уязвимость глазами атакующего полезно — так понятнее, где ставить защиту. Но «взгляд атакующего» здесь означает **модель угроз и экономику атаки**, а не пошаговый рецепт. Рецепт мы не дадим принципиально: ему два дня, он бьёт по неаутентифицированному RCE, и половина серверов ещё не закрыта.

Что движет атакующим в такой ситуации:

* **Массовость важнее точности.** Когда уязвим «весь веб», никто не выбирает жертву прицельно. Запускается широкое сканирование: пробуем всех подряд, закрепляемся у тех, у кого сработало. Ваш сайт попадает под удар не потому, что вы интересны, а потому что вы существуете и отвечаете на запросы.
* **Гонка с патчем.** Ценность эксплойта максимальна в первые дни, пока массы не обновились. Отсюда всплеск активности сразу после раскрытия — он уже наблюдается.
* **Обход фильтров.** Как только вендоры WAF выкатили правила, атакующие начали мутировать полезную нагрузку, чтобы под них не попадать. Это уже зафиксировал Cloudflare. Вывод для вас: WAF — это выигранное время, а не победа. Побеждает только патч.
* **Автоматизация на их стороне тоже.** Если ИИ помог найти и раскрутить уязвимость за часы на стороне исследователей, то и на стороне нападающих цикл «от CVE до массового сканера» стал короче, чем когда-либо.

Практический смысл этой оптики один: не рассчитывайте, что «мой маленький сайт никому не нужен». В мире широковещательных атак не нужных сайтов не бывает.

---

<a id="responders"></a>
## Кто уже бросился чинить

Хорошая новость: индустрия отреагировала на PHP2Shell как слаженный организм, и это, пожалуй, лучшая иллюстрация того, что экосистема PHP жива и здорова. Раскрытие было скоординированным — к часу X защита уже стояла.

* **Cloudflare** выкатил правила WAF **примерно за 9 часов до публичного раскрытия** и включил защиту по умолчанию 21 октября в 3:02 UTC — на всех планах, включая бесплатный, без действий со стороны клиента. По их данным, они уже видят атакующий трафик и его мутации.
* **Fastly, Akamai, Imperva** — выкатили собственные защитные правила для клиентов, которые не могут обновиться мгновенно.
* **AWS, Google Cloud, Microsoft, Vercel** — опубликовали руководства по реагированию и защиту на уровне своих платформ.
* **Automattic** (компания за WordPress.com) и другие участники экосистемы — в списке тех, кто помогал со скоординированным ответом.

Отдельно стоит отметить саму команду безопасности PHP: два месяца тихой работы, синхронный выпуск патчей по всем поддерживаемым веткам и даже бэкпорты для веток, у которых официальная поддержка уже закончилась (7.4, 8.0, 8.1). Для проекта, который годами хоронят в комментариях, это образцовая реакция.

---

<a id="victims"></a>
## Есть ли уже пострадавшие

Здесь важно быть честным и не множить панику. **На третий день после раскрытия публично подтверждённых взломов именно через PHP2Shell нет.** Ни одна крупная организация пока не названа жертвой.

Но несколько вещей известны точно:

* Рабочие эксплойты существуют — они продемонстрированы исследователями против свежих образов WordPress, Drupal и Joomla. Это демонстрация поверхности, а не корень проблемы: дело не в этих CMS, а в PHP под ними.
* Сканирование и попытки эксплуатации уже идут — об этом говорят и Cloudflare, наблюдающий атакующий трафик, и отраслевые сводки, фиксирующие «появление попыток эксплуатации».
* Отсутствие публичных жертв на третий день — это не «пронесло», а «ещё рано». Между массовым сканированием и первыми публичными отчётами о взломах обычно проходят недели. Окно, в которое нужно успеть обновиться, открыто прямо сейчас.

Проще говоря: тишина на табло — это не отбой, а фора. Используйте её.

---

<a id="defense"></a>
## Как защититься: по шагам

### 1. Обновите PHP — это единственное настоящее решение

Всё остальное ниже — подпорки, которые покупают время. Закрывает дыру только патч.

```bash
# Debian/Ubuntu, репозиторий Ondřej Surý (как у нас)
sudo apt-get update
sudo apt-get install --only-upgrade -y \
  $(dpkg-query -W -f='${db:Status-Abbrev} ${Package}\n' 'php8.5*' | awk '$1 == "ii" {print $2}')

# Перезапустить всё, что держит старый бинарник в памяти
sudo systemctl restart php8.5-fpm
sudo supervisorctl restart all   # воркеры очередей — это тоже PHP
```

Целевые версии: **8.5.12 / 8.4.27 / 8.3.36 / 8.2.35** или новее. Проверьте и CLI, и FPM:

```bash
php -v | head -1
/usr/sbin/php-fpm8.5 -v | head -1
```

> [!WARNING]
> Перезапуск PHP-FPM обязателен. Долгоживущий процесс держит старый, уязвимый бинарник в памяти даже после `apt upgrade`, пока его не перезапустить. То же касается воркеров очередей под Supervisor или Horizon — они не видят новый PHP до перезапуска.

Подробно про обновление и пересборку образов — в нашем разборе [production-образа для PHP](../tools/dockerfile-php-best-practices).

### 2. Поднимите WAF

Если вы за Cloudflare — защита уже включена по умолчанию, проверьте только, что правила в режиме блокировки. Fastly, Akamai, Imperva и облачные провайдеры выкатили аналогичное. Помните про мутацию payload: WAF — временная мера.

### 3. Ограничьте тело запроса на границе

На обратном прокси (nginx, балансировщик) отрежьте аномально большие тела запросов до того, как они дойдут до PHP. Это не лечит, но сбивает значительную часть автоматических попыток.

### 4. Прикройте вторую дверь настройками

Если патч пока не раскатан — отключите механизмы, через которые работает CVE-2026-109619. DevSense ими не пользуется, на работу сайта это не влияет:

```ini
; /etc/php/8.5/fpm/conf.d/99-hardening.ini
session.upload_progress.enabled = 0
fatal_error_backtraces = 0   ; только PHP 8.5
expose_php = Off
```

```bash
sudo systemctl restart php8.5-fpm
```

Это снижает экспозицию, но **не заменяет обновление**.

---

<a id="detection"></a>
## Как увидеть атаку в своих логах

Защита без наблюдаемости слепа. Вот честные индикаторы, на которые стоит смотреть (ни один из них сам по себе не доказывает взлом — важна корреляция):

* **В логах PHP-FPM:** `Allowed memory size ... exhausted` в связке с `Unknown on line 0`. Строка `on line 0` означает, что падение произошло на этапе инициализации запроса, ещё до кода приложения, — именно там живёт первая дверь.
* **Падения воркеров:** сегфолты (`SIGSEGV`, `exited on signal 11`) в логах PHP-FPM или Apache, особенно сериями.
* **Аномальные запросы:** POST с необычно длинными именами полей (порядка мегабайтов), бинарные данные и нулевые байты в значениях полей.
* **Необычно большие cookie `PHPSESSID`** — один из признаков, на которые указывают сами исследователи.
* **Процессы-сироты от веб-пользователя:** шелл, запущенный от `www-data`, — это уже не признак, а почти приговор:

```bash
ps -eo user,pid,ppid,cmd | awk '$1=="www-data"' | grep -vE "php-fpm|nginx"
sudo grep -h "Unknown on line 0" /var/log/php8.5-fpm.log* 2>/dev/null | tail
```

Как встроить такие сигналы в постоянный мониторинг и алерты — в статье про [наблюдаемость](observability-monitoring-laravel).

---

<a id="php-alive"></a>
## PHP жив — и это доказательство

PHP хоронят с завидной регулярностью. «Мёртвый язык», «легаси», «все ушли на Node и Go» — этот некролог пишут каждый год. PHP2Shell, как ни парадоксально, — аргумент ровно в обратную сторону.

Во-первых, уязвимость такого масштаба возможна только у технологии, на которой реально стоит огромная часть веба. Мёртвые языки не попадают в заголовки CISA и не заставляют Cloudflare выкатывать защиту за девять часов до раскрытия. В дыру размером с 70% интернета проваливается только то, что этот интернет держит.

Во-вторых — и это главное — посмотрите на реакцию. Команда безопасности PHP провела образцовое скоординированное исправление, выпустила патчи по всем веткам синхронно и даже бэкпортировала фиксы в ветки без официальной поддержки. Вся индустрия — от Automattic до AWS — отработала как единый организм. Так ведёт себя не умирающий проект, а зрелая, живая экосистема с взрослыми процессами.

PHP 8.5 с property hooks, асимметричной видимостью, типизированными свойствами и pipe-оператором — это современный язык, а не музейный экспонат. У живого есть иммунная система, и в октябре 2026 года она сработала быстро и слаженно. Живее всех живых — в том числе потому, что умеет быстро залечивать такие раны.

---

<a id="checklist"></a>
## Чеклист

1. PHP обновлён до 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35 или новее — и CLI, и PHP-FPM.
2. PHP-FPM перезапущен; воркеры очередей (Supervisor/Horizon) перезапущены.
3. Проверено, что процесс FPM не держит старый бинарник (`/proc/<pid>/exe` без пометки `(deleted)`).
4. WAF включён и в режиме блокировки; помните про временность этой меры.
5. На границе ограничен размер тела запроса.
6. Если патч не раскатан — отключены `session.upload_progress.enabled` и `fatal_error_backtraces`.
7. Логи проверены на `Unknown on line 0`, сегфолты и шеллы от `www-data`.
8. Образы контейнеров пересобраны и передеплоены, если PHP ставится из образа.

---

## Итог

PHP2Shell — редкий случай, когда уязвимость интересна не только тем, что она ломает, но и тем, что она показывает. Ломает она фундамент: неаутентифицированный RCE в ядре, под которым стоит большая часть веба. А показывает — что экосистема вокруг этого ядра жива, быстра и слаженна. Патч вышел, большие игроки закрыли собой тех, кто не успел, а от вас требуется одно и простое действие: обновиться и перезапуститься. Сделайте это раньше, чем закончится фора.

---

<a id="self-test-quiz"></a>
## Квиз для самопроверки

### Вопрос 1: Почему PHP2Shell опаснее типичной уязвимости в плагине CMS?
- А) Потому что её сложнее обнаружить сканерами.
- Б) Потому что она в ядре PHP, на пути разбора запроса, и срабатывает до кода приложения — без авторизации и вне зависимости от CMS или фреймворка.
- В) Потому что она затрагивает только устаревшие версии PHP.

<details>
<summary>Показать правильный ответ</summary>

**Правильный ответ: Б**
Дефект живёт на первом слое обработки запроса, общем для всех PHP-приложений. Ни логин, ни конкретная CMS, ни уязвимый плагин не нужны — достаточно, чтобы сервер принимал запросы и выполнял PHP.
</details>

### Вопрос 2: Почему после `apt upgrade` обязательно перезапускать PHP-FPM и воркеры очередей?
- А) Иначе не обновятся файлы конфигурации.
- Б) Потому что долгоживущие процессы держат старый, уязвимый бинарник PHP в памяти, пока их не перезапустить.
- В) Чтобы сбросить OPcache от статических страниц.

<details>
<summary>Показать правильный ответ</summary>

**Правильный ответ: Б**
PHP-FPM и воркеры очередей — это долгоживущие процессы. Они продолжают исполнять старый бинарник, загруженный в память, даже после обновления пакета, пока не будут перезапущены. Проверить можно по символьной ссылке `/proc/<pid>/exe`.
</details>

### Вопрос 3: Почему WAF — это выигранное время, а не полное решение?
- А) WAF замедляет сайт и его приходится отключать.
- Б) Потому что атакующие мутируют полезную нагрузку, чтобы обходить правила, — закрывает дыру только обновление PHP.
- В) Потому что WAF защищает только от аутентифицированных атак.

<details>
<summary>Показать правильный ответ</summary>

**Правильный ответ: Б**
Правила WAF фильтруют известные формы атаки, но нападающие уже мутируют payload, чтобы под них не попадать (это зафиксировал Cloudflare). WAF снижает риск и покупает время на обновление, но единственное полное решение — патч.
</details>