CVE-2026-109618 & CVE-2026-109619 — PHP Pre-Auth RCE Exploit & Detection Toolkit
Exploits · Detection · Lab · Writeup
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 | GHSA | CVSS | Description |
|---|---|---|---|
| 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 | Producer: any session_start() endpoint; Consumer: any endpoint |
FPM |
Chain D is the most critical: zero-dependency pre-auth RCE against any Apache mod_php installation.
Chain E is nearly as broad on FPM: the producer needs any endpoint that calls session_start() (near-universal — WordPress, Laravel, Joomla, Drupal all do), and the consumer can be any PHP endpoint — the rfc1867 upload_progress handler runs during SAPI startup before application code. Verified: nosession.php (no session_start() in code) triggers 502 crash when consuming stale BG(unserialize) state.
Three RCE exploits (Chains A, B, C) are included in exploit/:
| File | Chain | What It Does |
|---|---|---|
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 |
Chains D and E exploits are available to paid subscribers.
# Chain A: Session injection + LFI → 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)
php exploit/chain_b_uaf_rce.php
# 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/:
| File | Format | Signatures |
|---|---|---|
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 https://github.com/ikow/php2shell-poc.git && cd php2shell-poc
# Start the lab (PHP-FPM + nginx + Apache mod_php)
cd lab && docker compose up -d
# Verify each chain
python3 ../poc/verify_session_injection.py --target http://127.0.0.1:18080
python3 ../poc/verify_handler_mismatch.py --target http://127.0.0.1:18080
python3 ../poc/verify_oom_trigger.py --host 127.0.0.1 --port 18081
python3 ../poc/verify_fpm_stale_state.py --target http://127.0.0.1:18080
# Run an exploit
python3 ../exploit/chain_a_session_lfi.py --host 127.0.0.1 --port 18080 --command 'id'php2shell-poc/
├── exploit/
│ ├── 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
├── detection/
│ ├── php2shell.rules # Suricata / Snort IDS rules
│ ├── php2shell.yaml # Sigma SIEM detection rules
│ ├── modsecurity.conf # ModSecurity WAF rules
│ └── php2shell.lua # OpenResty / Nginx Lua WAF module
├── poc/
│ ├── 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
├── lab/
│ ├── docker-compose.yml # PHP-FPM + nginx + Apache mod_php
│ ├── setup.sh # One-click lab setup
│ └── php.ini / php-apache.ini # Vulnerable PHP configs
└── docs/
├── ANALYSIS.md # Full technical analysis
└── substack_article.md # Writeup source
; Immediate — reduces attack surface
session.upload_progress.enabled = Off
session.use_only_cookies = OnThe 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:
| Platform | Vulnerable | Notes |
|---|---|---|
| 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
This repository is for authorized security testing and educational purposes only. Exploit code for Chains D and E (zero-dependency RCE) is available to paid subscribers of the writeup.
MIT
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
