CVE-2026-109619 (PHP2Shell): Pre-Auth Remote Code Execution (RCE) via PHP-FPM Stale Global State Deserialization UAF. Reproducible Docker lab, interactive shell, reverse shell & WAF/IDS rules.
# CVE-2026-109619: PHP2Shell — Security Research Lab & PoC
<p align="center">
<img src="https://img.shields.io/badge/CVE-2026--109619-critical?style=for-the-badge&logo=shield&logoColor=white&color=e11d48" alt="CVE-2026-109619">
<img src="https://img.shields.io/badge/CVSS%204.0-9.2%20CRITICAL-red?style=for-the-badge&color=dc2626" alt="CVSS 9.2">
<img src="https://img.shields.io/badge/Exploit-RCE%20Verified-success?style=for-the-badge&color=16a34a" alt="RCE Verified">
<img src="https://img.shields.io/badge/Affected-PHP--FPM%208.2--8.5-blue?style=for-the-badge&color=2563eb" alt="Affected Platforms">
<img src="https://img.shields.io/badge/License-MIT-gray?style=for-the-badge" alt="MIT License">
</p>
A comprehensive research lab and exploit reproduction toolkit for **CVE-2026-109619** (also known as **PHP2Shell**), a critical vulnerability in PHP's deserialization subsystem affecting persistent worker architectures (such as **PHP-FPM**), enabling pre-auth cross-request use-after-free and arbitrary remote code execution under the privileges of the web process.
<p align="center">
<img src="assets/showcase.gif" alt="CVE-2026-109619 Exploit Demonstration" width="850">
</p>
---
## 1. Technical Analysis (Root Cause Analysis)
### Vulnerability Overview
- **Component:** PHP Deserialization Subsystem (`ext/standard/var_unserializer.re`)
- **Affected Versions:** PHP `8.2.0`–`8.2.34`, `8.3.0`–`8.3.35`, `8.4.0`–`8.4.26`, `8.5.0`–`8.5.11`
- **Vulnerability Class:** CWE-672: Operation on Resource After Expiration or Release / CWE-416: Use After Free
- **CVSS Score:** 9.2 (CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N)
### Defect Mechanics
1. **Unchecked Bailout in Deserialization:**
During deserialization, `php_var_unserialize_init()` initializes reference tracking structures and destruction chains in `BG(unserialize).data`, incrementing `BG(unserialize).level = 1`. If an in-script fatal error or memory exhaustion occurs (e.g. inside `__wakeup(