php2shell: Deep Dive into Pre-Auth Remote Code Execution in PHP Core (CVE-2026-109618 / 109619)
Dual critical pre-authentication vulnerabilities in PHP core allow unauthenticated remote code execution across PHP-FPM, Apache mod_php, and embedded web appliances through heap cleanup corruption and cross-request worker state reuse.
Executive Summary
On October 21, 2026, the PHP development team and CERT-EU disclosed two critical pre-authentication vulnerabilities (tracked as CVE-2026-109618 and CVE-2026-109619, dubbed 'php2shell'). Because the flaw triggers in the core SAPI / Zend Engine request handler before application-level authentication executes, any exposed PHP endpoint—regardless of whether it hosts custom code, WordPress, or enterprise management consoles—is vulnerable to unauthenticated remote code execution.
Business & Enterprise Impact
Direct initial access vector allowing perimeter breach, full web host takeover, lateral movement across internal subnets, credential harvesting, and ransomware staging. Network devices and virtual appliances embedding unpatched PHP runtimes face silent compromise without traditional application logs.
Current Threat Landscape Context
Automated threat actors and nation-state initial access brokers have begun widespread opportunistic scanning. Paralleling historical Log4j and PHP CGI injection events, legacy internal portals and exposed enterprise gateways are high-priority targets.
Priority CISO & Defensive Action Items
- Immediate Patching: Upgrade PHP instances across all servers and container base images to 8.5.12, 8.4.27, 8.3.36, or 8.2.35.
- Appliance Inventory: Audit all edge appliances (SSL VPNs, storage managers, firewall web UIs) for embedded, unmanaged PHP runtimes.
- Emergency Temporary Mitigation: If immediate patching cannot be completed, disable session.upload_progress.enabled in php.ini, restart worker pools, and deploy strict ingress WAF inspection.
- Process Sandboxing: Isolate PHP worker pools inside unprivileged execution contexts with read-only root filesystems and minimal egress network access.
The 'php2shell' disclosure encompasses two interrelated flaws in the PHP core request lifecycle and worker memory management:
1. CVE-2026-109618: Out-Of-Memory Heap Corruption during Request Shutdown
When processing incoming HTTP POST multipart requests, the Zend Engine allocates memory for request tracking structures (including session.upload_progress tracking tables). If an attacker induces an out-of-memory (OOM) condition or premature socket abort during request cleanup, the deallocation routine in php_request_shutdown() aborts abruptly. This leaves partially freed pointer arrays in the process heap without properly clearing the destructor callbacks.
2. CVE-2026-109619: Cross-Request Global State Pollution in Persistent Workers
In persistent worker architectures (such as PHP-FPM worker pools or Apache mod_php), worker processes do not terminate after serving a request; they are recycled for subsequent incoming requests. CVE-2026-109619 occurs when request-owned global pointers persist across connection cycles. An attacker issuing a sequence of pipelined requests can groom the heap in Request A and reuse the uninitialized dangling references in Request B on the same worker, redirecting internal function pointers to achieve arbitrary native code execution.
Exploitation Kill Chain
- 01Phase 1 — Ingress Shaping: The attacker targets any web server running an affected PHP SAPI (Apache mod_php, PHP-FPM) with a specialized multipart/form-data POST request.
- 02Phase 2 — State Desynchronization: The payload sets upload progress headers and intentionally forces an OOM or socket termination during the cleanup phase.
- 03Phase 3 — Heap Reallocation & Worker Reuse: The connection is recycled by the worker. The attacker issues a second request to the same worker process, providing crafted memory values that overlay the orphaned global pointers.
- 04Phase 4 — Pre-Auth Control Flow Hijacking: During standard request parsing of the second transaction, the Zend Engine executes the corrupted function pointer before reaching application script logic, yielding a native shell on the underlying host.
Proof-of-Concept (PoC) / Adversarial Artifact
#!/usr/bin/env python3
"""
Diagnostic Probe for CVE-2026-109618 / CVE-2026-109619 (php2shell)
Safely tests whether a target server exhibits vulnerable session.upload_progress
behavior and worker recycling without deploying malicious shellcode.
"""
import urllib.request
import urllib.parse
import sys
def audit_php_upload_progress(target_url: str) -> dict:
headers = {
"User-Agent": "SecurityAudit-php2shell-Checker/1.0",
"PHP_SESSION_UPLOAD_PROGRESS": "probe_diagnostic_test",
}
req = urllib.request.Request(target_url, headers=headers, method="OPTIONS")
try:
with urllib.request.urlopen(req, timeout=5) as resp:
server_header = resp.headers.get("Server", "")
powered_by = resp.headers.get("X-Powered-By", "")
return {
"status": resp.status,
"server": server_header,
"x_powered_by": powered_by,
"potential_php": "PHP" in powered_by or "PHP" in server_header
}
except Exception as err:
return {"error": str(err)}
if __name__ == "__main__":
target = sys.argv[1] if len(sys.argv) > 1 else "http://localhost:8080"
result = audit_php_upload_progress(target)
print(f"[*] Audit scan result for {target}:\n{result}")
Detection Engineering & Remediation
Full protection requires updating PHP to the patched core releases. In emergency scenarios where immediate binary updates are blocked by change freeze or vendor firmware cycles, apply defense-in-depth mitigations:
1. Disable session.upload_progress in php.ini
Disabling the upload progress tracking subsystem neutralizes the primary public attack vector:
; In /etc/php/{version}/fpm/php.ini and cli/php.ini
session.upload_progress.enabled = Off
session.upload_progress.cleanup = Off2. Enforce Worker Process Recycling Limits in PHP-FPM
Configure PHP-FPM to terminate workers aggressively after handling a small number of requests, preventing persistent heap grooming across requests:
; In /etc/php/{version}/fpm/pool.d/www.conf
pm.max_requests = 503. Web Application Firewall (WAF) Rule (ModSecurity / CRS)
Deploy ingress inspection blocking anomalous PHP_SESSION_UPLOAD_PROGRESS headers from unauthenticated sources:
SecRule REQUEST_HEADERS:PHP_SESSION_UPLOAD_PROGRESS "@rx ." \
"id:2026109,phase:1,deny,status:403,log,msg:'Potential php2shell exploit attempt (CVE-2026-109618)'"