No. 20 · 2 November 2026 · Updated 2 November 2026 · Security · Vulnerabilities

PHP2Shell: count evidence stages, not branded requests

Read as verdicts, the early PHP2Shell reports look like a fight. Read as stages of one exploit chain, they agree. What a SOC can establish at each stage, why a leak is an incident without a shell, and why no server setup counts as a patch.

PHP2Shell is the name given to two PHP vulnerabilities, CVE-2026-109618 andCVE-2026-109619, patched on 21 October 2026 [12, 13]. Within a week the public record held a vendor saying none of the attempts it saw had succeeded 1, a honeypot researcher documenting 35 shells 2, a security firm announcing and then withdrawing a compromise8, and a CISA listing as known exploited 3. Read as verdicts, that looks like a fight. It isn't. Each source was scoped to what it could see, and the useful question for a SOC is what each one actually observed. This essay sorts the public evidence by stage, using the four-stage chain that Adel Karimi's honeypots recorded: memory pressure, a leak, more pressure, a shell 2. Three things follow. First, a request that fails to produce a shell can still have leaked memory, which is its own incident. Second, PHP-FPM is not shown to be safe: the advisories list it as conditionally exposed, though no complete FPM exploit is public [12, 13]. Third, the status code, the patch level and the server type each answer a narrower question than they appear to, and the triage rules at the end say which.

In plain terms: PHP runs a large share of the web's server-side code, and these two bugs let a remote attacker corrupt a PHP worker's memory and, in the right conditions, run commands on the server. A SOC (security operations center) is the team that reads the alerts. CISA's KEV catalog is the U.S. government's list of vulnerabilities known to be exploited, which obliges federal agencies to patch by a deadline. An SAPI is the way PHP is attached to a web server: built into Apache as mod_php, run as a pool of workers under PHP- FPM, or started as a CGI process.

The Spider in the Bell Jar

Wiz's report of 27 October is subtitled "none have succeeded so far," and its conclusion says it had not yet seen successful end-to-end exploitation in its own telemetry 1. The same report says the scanners it watched did exploit Karimi's honeypot, that those targets used a favorable single-worker Apache mod_php setup, and that partners had privately disclosed working exploits against other targets 1. CISA added both CVEs to the KEV catalog on 26 October 3. Its criteria require reliable evidence of active exploitation, and count successful code execution on a honeypot as attempted exploitation 3. CISA didn't say which evidence it relied on 3.

So the sources never disagreed about facts. Each was careful about scope; the headlines weren't. The disagreement came from reading scoped observations as verdicts, and that's the habit the stage ladder is for. What it adds isn't a reconciliation. It's a way to say, for any one report or any one alert, how far the attacker is known to have got.

Early reporting showed why that matters. Sophos first posted on 21 October, updated at 16:18 UTC on 22 October to report one successful exploitation, and corrected that at 21:21 UTC the same day: there was no evidence of a successful compromise 8. Unit 42 retracted an update of 23 October two days later, saying it could not confirm that the initial access it had described came through these CVEs 7. Both corrections were honest and quick. Both are what happens when "success" is the only word available.

Karimi's report of 24 October covers three PHP 8.4.26 honeypots running single-worker Apache mod_php with a 128 MiB memory limit 2. They recorded 35 shells from two clusters of addresses, 3 from one and 32 from the other 2. Karimi ties the activity to CVE-2026-109618 and says the exact tooling is unconfirmed 2.

He labels the four requests A1, B1, A2 and B2. The letter is the kind of step: A is memory pressure, B is the payoff. The number is the round. Out loud, that's pressure, leak, pressure, shell. This is the shape of one observed exploit family, not a model of every possible exploit of either CVE; the advisories describe each bug as reaching code execution by its own mechanism [12, 13].

Pressure (A1). A large multipart upload drives the worker to PHP's memory limit 2. In Karimi's logs that request completed with HTTP 200, and he notes that a 200 on the first three requests is not the success criterion 2. Prophet Security's guidance looks for HTTP 500 instead 11. So the status code can't decide anything here, in either direction. What an analyst can establish at this stage is an attempt: a memory-exhaustion error tied to a suspicious upload.

Weighing the Biscuit

Leak (B1). The next request carries the session upload-progress field, and the response sets a PHPSESSID cookie that decodes to 819,200 bytes 2. A session cookie is normally a few dozen characters. Those 800 KiB are server memory, sent to the attacker. That's a confidentiality incident whether or not a shell follows. A leak that never becomes a shell is still a leak.

Pressure again (A2). A second round of memory pressure, which depends on what the leak returned 2. On its own it looks like A1, so it can't be identified independently; it shows up as the third request in a sequence from the same source. Record it as an attempted stage with an unresolved outcome.

Shell (B2). A shell process starts with the Apache worker as its parent, running as the web server's user 2. Karimi links the network sequence to that process through host-level telemetry; the PID Apache logged inside the container is a different number from the one the host sees, so a naive PID match fails 2. B2 is unauthorized code execution with the web server's privileges. It isn't root, and it isn't the whole host. In the PAN-OS campaign below, root took a second, kernel vulnerability 6.

The Bicycle Pump

Wiz used the same labels for what its sensors saw: A1 attempts that reached the memory limit but failed to leak anything usable, so no B1 and nothing after it 1. That's a record of where those attempts stopped, which is exactly the kind of statement the ladder makes easy.

Why did the honeypots fall and Wiz's sensors hold? Partly configuration, and partly the fact that nobody has measured how much. What's public, by setup:

SetupShown in publicStatus
mod_php , one workerFull chain [2]Established
mod_php , many workersNothing publicUnknown
PHP-FPM, defaultsPath needs app help [12]Plausible
FPM, max_requests=1Suggested mitigation [12]Partial
IIS FastCGI, PHP 7.1Shells, attributed [11]Plausible

That table is our reading of the sources, not a measurement, and the statuses are our assessment.

The Patched Hull

The FPM row is the one people want to lean on, so here's exactly what the advisories say. Both note that FPM exits a worker when request startup fails [12, 13], which removes the state a later request would need. For the stale-state bug, a validated path works on a normal dynamic FPM pool but depends on a suitable application operation 12. For the memory- exhaustion bug, no complete FPM exploit has been demonstrated 13. The PHP Foundation reports that code execution was also confirmed on FPM through application-level code paths 4. And no public report shows FPM exploited in the wild. So FPM is conditionally exposed and undemonstrated: an untested chain, not a safe harbor. The case for patching FPM rests on the advisories listing it as exposed, not on any attack anyone has shown.

One FPM myth is easy to retire. Does FPM start a fresh worker for every request? No. pm.max_requests sets how many requests a worker serves before it's replaced, and the default, 0, means no limit 5. Believing otherwise after reading the manual turns an honest mistake into a mumpsimus. (The manual describes the default. Your fleet may not have read the manual.) The stale-state advisory suggests pm.max_requests=1 where performance allows 12; that narrows the window, and it doesn't replace the patch.

Three Patched Roofs

Prophet Security describes php-cgi.exe starting cmd.exe across four PHP workers on IIS, on end-of-life PHP 7.1, and calls it "consistent with" PHP2Shell 11. That's an attribution, not a confirmation. If it holds, the bugs aren't specific to mod_php.

The one production campaign on record is Dream Research's: attackers chained PHP2Shell with a Linux kernel privilege escalation, CVE-2026-46300, to get root on internet-exposed PAN-OS management interfaces, 24 firewalls and a management server 6. Unit 42 says it independently verified the attacker's tooling and Dream's reported results 7. The appliances ran PHP 8.0.30 and 7.4.33 6, branches that received no fix, and neither report names the SAPI, so the campaign says nothing about FPM either way [6, 7].

The long version of this story starts earlier than most retellings. The PHP Foundation says its developers found the first signs of the memory-exhaustion problem in 2024 4. Calif found the exploitable bugs on 1 August 2026, with help from what its write-up calls an LLM companion, and reported the first to PHP on 11 August and the second on 21 August 10.

DateWhat the record shows
1 AugCalif finds the bugs [10]
11 AugFirst bug reported to PHP [10]
17 OctAttempt seen in AWS MadPot [9]
20 OctCVE IDs leak; demo video [4]
21 OctFixed releases out [4]
22 OctSophos claim and retraction [8]
24 OctKarimi documents shells [2]
26 OctCISA adds to KEV [3]
The Cloud Under Glass

AWS found an exploitation attempt dated 17 October in its MadPot honeypot telemetry 9. That's an attempt, three days before anything leaked, and it means someone had working knowledge of the bugs before disclosure. It isn't evidence of a compromise, and AWS doesn't call it the first. Its caveat that it's unclear whether attempts would have succeeded on real systems refers to later attempts, on 21 October 9.

The Folded Fireworks

On 20 October, around 15:00 UTC, the two CVE IDs began circulating on forums and social media, without technical details 4. Around 20:00 UTC Calif mistakenly published a demonstration video, which the Foundation says contributed to the accelerated development of proofs of concept 4. The Foundation brought the release forward from 22 October to 14:00 UTC on 21 October, and says it hadn't identified any functional exploits at that point 4.

Did AI compress all this into hours? The timeline can't say how much AI contributed; AI helped Calif find the bugs 10, and the Foundation says AI-assisted research has raised the volume of reports it receives 4. What the timeline does show is that the "hours" were leak to release, about 23 hours, forced by an embargo that broke. Discovery to release took eleven weeks, and the underlying problem had been seen two years earlier.

Trust, but correlate. Keep three things separate in every ticket: the stage you suspect, the evidence you observed, and the impact you've confirmed. Missing telemetry is "unknown," never "failed."

The Diving Bell

First, the version, because it decides what happens next and not what already happened. At or above 8.2.35, 8.3.36, 8.4.27 or 8.5.12, the two CVEs are fixed; below 8.2, upgrade, because those branches got nothing 4. Distribution and appliance packages backport fixes, so check the vendor's advisory, not just the version string. Sophos also reports a later related fix, CVE-2026-115560, on 23 October 8. Then look back regardless. A host patched on 22 October could have been compromised on 21 October; patch state never closes an incident, and the earliest public sign of exploitation is 17 October 9.

Then the stages. Pressure: a memory-exhaustion error in PHP's log, tied to a large multipart upload, whatever the status code. That establishes an attempt. Leak: a request carrying the upload-progress field, answered with an abnormally large session cookie. That establishes disclosure: assess what memory went out and what your reporting duties are, before anyone asks about shells. Pressure again: the next request in the same sequence; record it, don't grade it. Shell: a process whose parent is the web server worker, running as the web user, close in time to the sequence. Correlate through host-level telemetry, since container and host PIDs differ. That establishes code execution as the web user, and the investigation then has to find out whether it went further.

And the rule that keeps coming up: never downgrade an alert because the server runs FPM. Severity follows the evidence; the SAPI only changes the odds.

The Ring of Pages

Every source in this story was right about what it saw. The trouble came from collapsing four stages into one word. Name the stage you observed, keep a leak separate from a shell and a patch separate from an all-clear, and the reports stop looking like they disagree. Four stages, thirteen sources, and the answer is still the patch.

  1. H1 (worker persistence): A complete cross-request chain needs the requests that create the stale state and the request that uses it to run in the same surviving worker.
    • Disproof: an instrumented, reproducible complete chain across a verified worker replacement, without reacquiring the state another way.
  2. H2 (worker count): In otherwise identical FPM deployments, eight workers cut the rate of complete chains by at least half compared with one worker.
    • Disproof: in a preregistered comparison, the eight-worker success rate is more than half the one-worker rate, outside its confidence interval.
  3. H3 (FPM defaults): PHP-FPM with default settings is not exploitable without application-specific behavior.
    • Disproof: a documented complete chain on default FPM with no application- specific operation in the path.
  4. H4 (both CVEs): Every complete chain seen in the wild uses both CVEs.
    • Disproof: a confirmed complete chain that uses only one. The advisories describe each as reaching code execution alone, which already points that way [12, 13].

The first version went up on 2 November 2026 and was revised the same day after reviews by Claude, Gemini and Astra, checked against every source. It graded "FPM can succeed through pool saturation" as established, which no source says; its triage code tested for HTTP 500 where Karimi recorded 200, looked for the upload-progress marker in the response instead of the request, matched PIDs that can't match, and let a patched version mark a host "mitigated"; it gave FPM a "medium reliability" nothing measured; it misquoted Wiz, misplaced AWS's caveat, called the 17 October attempt the first, and said the release was scheduled when it was brought forward; it rebutted claims nobody notable had made; and it carried three figure placeholders and a stray pipeline label. All of those are gone. The first version is kept, unchanged, in the issue's source folder.

ClaimSourceSource typeStatus
Four-request chain on the honeypots[2]Researcher's captureEstablished
Pressure request returned HTTP 200[2]Researcher's captureEstablished
Leak cookie decoded to 819,200 bytes[2]Researcher's captureEstablished
Shell's parent was the Apache worker[2]Researcher's captureEstablished
No end-to-end success in Wiz telemetry[1]Vendor's reportEstablished
FPM exits a worker on failed startup[12] [13]Upstream advisoryEstablished
Complete chain possible on default FPM[4] [12]Upstream, app- dependentPlausible
FPM exploited in the wildnoneNot reportedUnknown
pm.max_requests defaults to 0[5]ManualEstablished
Attempt seen on 17 October[9]Vendor's reportEstablished
That attempt succeedednoneNot reportedUnknown
Sophos claim withdrawn same day[8]Vendor's reportEstablished
25 PAN-OS hosts rooted with a kernel bug[6] [7]Researcher, corroboratedPlausible
IIS cases are PHP2Shell[11]Vendor's attributionPlausible
Every wild chain needs both CVEsnoneUntestedBest guess
Leak to release about 23 hours[4]Upstream accountEstablished

References

  1. 01Wiz (Shriki, Y., Dorfman, S., Blachsan, A. and Samuel, Y.). "PHP2Shell: Exploitation Attempts and Remediation Trends." Wiz blog, 27 October 2026. https://www.wiz.io/blog/php2shell-exploitation-so-far (accessed 2026-11-02).
  2. 02Karimi, A. "PHP2Shell confirmed RCE." honeypot-data, GitHub, 24 October 2026. https://github.com/0x4D31/honeypot-data/blob/main/reports/php2shell/2026-10-24-confirmed-rce.md (accessed 2026-11-02).
  3. 03CISA. KEV bulletin adding CVE-2026-109618 and CVE-2026-109619, 26 October 2026, https://content.govdelivery.com/accounts/USDHSCISA/bulletins/4309083; KEV catalog criteria, https://www.cisa.gov/known-exploited-vulnerabilities (both accessed 2026-11-02).
  4. 04The PHP Foundation. "Today's PHP Security Release, and How We're Strengthening PHP Security." 21 October 2026. https://thephp.foundation/blog/2026/10/21/todays-php-security-release-and-how-were-strengthening-php-security/ (accessed 2026-11-02).
  5. 05PHP Manual. "FPM configuration: pm.max_requests." php.net. https://www.php.net/manual/en/install.fpm.configuration.php (accessed 2026-11-02).
  6. 06Dream Research. "Chained PHP2Shell Exploit Roots 25 Servers." 26 October 2026. https://dreamgroup.com/blog/chained-php2shell-exploit-roots-25-servers (accessed 2026-11-02).
  7. 07Unit 42. "CVE-2026-109618 and CVE-2026-109619." Palo Alto Networks, updated through 29 October 2026. https://unit42.paloaltonetworks.com/cve-2026-109618-cve-2026-109619/ (accessed 2026-11-02).
  8. 08Sophos. "Proof of Concept exploit released for PHP vulnerabilities 109618/109619." First posted 21 October 2026, updated through 29 October. https://www.sophos.com/en-us/blog/proof-of-concept-exploit-released-for-php-vulnerabilities-109618-109619 (accessed 2026-11-02).
  9. 09AWS. "Amazon Threat Intelligence Identifies PHP2Shell Exploitation Prior to Public Disclosure in MadPot." AWS Security Blog, 21 October 2026. https://aws.amazon.com/blogs/security/amazon-threat-intelligence-identifies-php2shell-exploitation-prior-to-public-disclosure-in-madpot/ (accessed 2026-11-02).
  10. 10Calif. "PHP2Shell." calif.io, undated. https://calif.io/php2shell/ (accessed 2026-11-02).
  11. 11Prophet Security. "PHP2Shell: Detecting and investigating CVE-2026-109618 and CVE-2026-109619." 27 October 2026. https://www.prophetsecurity.ai/blog/php2shell (accessed 2026-11-02).
  12. 12PHP. "RCE via stale global state" (CVE-2026-109619), GHSA-6wmf-4rv5-p3rp. php-src security advisories, GitHub, 21 October 2026. https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp (accessed 2026-11-02).
  13. 13PHP. "RCE via OOM corruption" (CVE-2026-109618), GHSA-w8hw-w9fx-j79w. php-src security advisories, GitHub, 21 October 2026. https://github.com/php/php-src/security/advisories/GHSA-w8hw-w9fx-j79w (accessed 2026-11-02).