Skip to content
Exploit for Improperly Controlled Sequential Memory Allocation in Php

Exploit for Improperly Controlled Sequential Memory Allocation in Php

Sploitus • October 21, 2026

Five independent RCE chains exploiting PHP's `session.upload_progress` and the Zend engine's OOM bailout. **14 years of vulnerable code** — PHP 5.4.0 (2012) through 8.5.11. Pre-auth. No application vulnerability required for some chains.

Impacts **78% of all websites** — including WordPress (43%), Joomla, Drupal, Laravel, Magento, and every default PHP installation.

**Author:** [Qi Deng](  |  **Writeup:** [Substack](  |  **Date:** 2026-10-21

| CVE-2026-109618 | [GHSA-w8hw-w9fx-j79w]( | 9.2 | OOM → `longjmp()` leaves Zend engine state invalid → RCE |

| CVE-2026-109619 | [GHSA-6wmf-4rv5-p3rp]( | 9.2 | Stale global state across FPM worker requests → UAF → RCE |

**Patch:** [Commit 3584a98]( — 300 files changed across the Zend engine.

| Chain | Vector | Pre-auth | Conditions | SAPI |

|-------|--------|:--------:|------------|------|

| **A** | Session injection + LFI | Yes | App has any LFI sink | All |

| **B** | var_destroy UAF → handler overwrite | No | App calls `unserialize()` | All |

| **C** | Handler mismatch → `__destruct` | Yes | Two dirs with different serialize_handler | FPM |

| **D** | OOM corruption → stale `EG()` | Yes | **None** — any endpoint | mod_php |

| **E** | FPM session OOM → stale `BG()` | Yes | Any `session_start()` endpoint | FPM |

Chain D is the most critical: **zero-dependency pre-auth RCE** against any Apache mod_php installation. No LFI, no app vulnerability, no authentication — just a single multipart POST.

Three RCE exploits (Chains A, B, C) are included in [`exploit/`](exploit/):

| `chain_a_session_lfi.py` | A | Injects PHP code via upload filename → LFI includes session file → RCE |

| `chain_b_uaf_rce.php` | B | var_destroy UAF → discovers `zif_system` via EG() → overwrites `var_dump` handler via `/proc/self/mem` → RCE |

| `chain_c_mismatch_rce.py` | C | Pollutes FPM worker `PS(serializer)` → injects serialized object via filename → `__destruct` fires on decode failure → RCE |

python3 exploit/chain_a_session_lfi.py --host TARGET --port 80 --command 'id'

# Chain B: var_destroy UAF → RCE (run on target or via uploaded webshell)

# Chain C: Handler mismatch → __destruct → RCE

python3 exploit/chain_c_mismatch_rce.py --host TARGET --port 80 --command 'id'

Pre-built IDS / WAF / SIEM rules in [`detection/`](detection/):

| `php2shell.rules` | Suricata / Snort | 13 rules — request, response, and recon |

| `php2shell.yaml` | Sigma | 5 rules — web logs, process creation, file events |

| `modsecurity.conf` | ModSecurity v2/v3 | 7 rules — drop-in for Apache/Nginx |

| `php2shell.lua` | OpenResty Lua | Lightweight reverse proxy module |

**Fastest mitigation:** block `PHP_SESSION_UPLOAD_PROGRESS` in multipart POST bodies. Near-zero legitimate use, covers the primary attack vector for both CVEs.

git clone && cd php2shell-poc

# Start the lab (PHP-FPM + nginx + Apache mod_php)

python3 ../poc/verify_session_injection.py --target

python3 ../poc/verify_handler_mismatch.py --target

python3 ../poc/verify_oom_trigger.py --host 127.0.0.1 --port 18081

python3 ../poc/verify_fpm_stale_state.py --target

python3 ../exploit/chain_a_session_lfi.py --host 127.0.0.1 --port 18080 --command 'id'

│ ├── chain_a_session_lfi.py # RCE: session injection + LFI

│ ├── chain_b_uaf_rce.php # RCE: var_destroy UAF → handler overwrite

│ └── chain_c_mismatch_rce.py # RCE: handler mismatch → __destruct

│ ├── php2shell.rules # Suricata / Snort IDS rules

│ ├── php2shell.yaml # Sigma SIEM detection rules

│ ├── modsecurity.conf # ModSecurity WAF rules

│ └── php2shell.lua # OpenResty / Nginx Lua WAF module

│ ├── verify_session_injection.py # Verify Chain A

│ ├── verify_uaf_asan.php # Verify Chain B (ASAN)

│ ├── verify_handler_mismatch.py # Verify Chain C

│ ├── verify_oom_trigger.py # Verify Chain D

│ └── verify_fpm_stale_state.py # Verify Chain E

│ ├── docker-compose.yml # PHP-FPM + nginx + Apache mod_php

│ ├── setup.sh # One-click lab setup

│ └── php.ini / php-apache.ini # Vulnerable PHP configs

├── ANALYSIS.md # Full technical analysis

└── substack_article.md # Writeup source

> **The only complete fix is patching PHP** to 8.2.35 / 8.3.36 / 8.4.27 / 8.5.12+. The OOM corruption (Chain D) is in the Zend engine core — no INI setting fixes it.

Wiz has demonstrated pre-auth RCE on stock container images:

| WordPress | Yes | Core doesn't use PHP sessions, but WooCommerce and many plugins do |

| Joomla | Yes | Uses native PHP sessions by default |

| Drupal | Yes | Uses native PHP sessions by default |

| Magento | Yes | Vulnerable even in maintenance mode |

| Laravel | Yes | `PendingBroadcast` is a known `__destruct` gadget |

- [PHP Security Advisory](

- [GHSA-w8hw-w9fx-j79w]( — CVE-2026-109618

- [GHSA-6wmf-4rv5-p3rp]( — CVE-2026-109619

- [Patch commit 3584a98]( — 300 files, Zend engine + extensions

- [Cloudflare WAF coverage](

- [Sansec analysis]( — PHPSESSID heap leak discovery

- [Wiz downstream impact](

- [Corelight detection]( — Zeek + Suricata community rules

Keywords: php2shell, CVE-2026-109618, CVE-2026-109619, PHP RCE, PHP exploit, session.upload_progress,

pre-auth RCE, PHP vulnerability, PHP session injection, PHP deserialization, PHP OOM, PHP memory corruption,

use-after-free, GHSA-w8hw-w9fx-j79w, GHSA-6wmf-4rv5-p3rp, WordPress RCE, Joomla RCE, Drupal RCE,

PHP security, WAF rules, Suricata rules, ModSecurity rules, IDS signatures, PHP 8.2.35, PHP 8.4.27,

session upload progress, PHP session fixation, rfc1867, longjmp, zend_bailout,

Snort rules, Sigma rules, detection rules, PHP patch, PHP critical vulnerability