---
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 та інші вже спостерігають сканування й спроби експлуатації, причому з мутацією payload для обходу фільтрів. За неавтентифікованого 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 викотили правила, атакувальники почали мутувати payload, щоб під них не потрапляти. Це вже зафіксував 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 уповільнює сайт і його доводиться вимикати.
- Б) Тому що атакувальники мутують payload, щоб обходити правила, — закриває діру лише оновлення PHP.
- В) Тому що WAF захищає лише від автентифікованих атак.

<details>
<summary>Показати правильну відповідь</summary>

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