PHP2Shell
Two bugs in how PHP handles incoming web requests let an attacker who has not logged in run code on the server. CVE-2026-109618 corrupts state when PHP runs out of memory. CVE-2026-109619 reuses stale global state in persistent workers. One combined upstream fix covers both.
Are you exposed?
- Affected: PHP builds that process untrusted HTTP requests through a web SAPI (mod_php, PHP-FPM). CVE-2026-109619 additionally concerns persistent workers, such as Apache mod_php and FPM pools.
- Fixed upstream: 8.5.12, 8.4.27, 8.3.36 and 8.2.35, all released 21 Oct. End of life branches 7.4, 8.0 and 8.1 got a source patch only.
- One combined fix covers both CVEs: php-src commit
31c0ea7d7ff1. - Check vendor patch status, not just the version string. Distro and vendor packages often backport the fix without changing the PHP version number.
- Restart after patching. Running PHP workers keep the vulnerable code in memory until they restart.
Remediation status.
Official patches come from php.net. Emphere backports are the upstream fix applied to the official release source, built, tested and signed, each with its applied patch, build log, test results and SBOM. For branches on request, we confirm what we can ship for your image in the reply.
Indicators of attack (IOAs).
- Request shape: large
multipart/form-dataPOSTs with an unusually high number of parts. In the observed attacks, bodies ranged from about 280 KB to 33 MB, with roughly 900 to 1,000 parts per request. Attackers can vary these numbers, so alert against your own upload baseline. - Mixed framing: the same client sends both
Transfer-Encoding: chunkedandContent-Lengthmultipart requests to the same endpoint. - Memory exhaustion fatals: PHP
Allowed memory size … exhaustederrors on these requests, logged during request startup (Unknown on line 0), with no matching application log entry. The failure happens before your code runs. - Memory disclosure: a response with an abnormally large
PHPSESSIDSet-Cookie, around 800 KB decoded. Normal session cookies are small. - The observed sequence: four requests against one Apache worker, retried until it succeeds.
- A chunked request, followed by memory exhaustion.
- A chunked request whose response carries the oversized session cookie.
- A Content-Length request, followed by memory exhaustion.
- A Content-Length request, followed by a shell and a worker crash.
- Correlate by worker. Tie requests to the same worker process using PID plus process start time, since PIDs are reused. Timestamps alone aren’t reliable when requests overlap.
None of these alone proves an attack. That includes a 500, a timeout, a worker crash, a missing access log line, or a single large upload; each can be benign.
Indicators of compromise (IOCs).
The confirmed IOC is a web server worker starting a shell.
- Process lineage from
httpd/apache2(and, by extension,php-fpm) tosh/bash/dash. - Unexpected file writes by the web user.
- Outbound connections from PHP workers.
- An Apache error log line like
child pid … exit signal Segmentation fault (11)right after one of the requests above.
- Isolate the host.
- Preserve logs and process evidence.
- Rotate any credentials the application could read.
- Redeploy from a patched image rather than cleaning in place.
Only updating is a complete fix. These steps reduce exposure to specific attack paths; they don’t make an installation safe. Steps marked PHP are from PHP’s 21 Oct security announcement.
- Restart every process that loads PHP: FPM pools, Apache, queue workers.
- Turn on your WAF or CDN vendor’s PHP2Shell rules.
