
Details of two critical PHP bugs leaked on Tuesday, October 20, ahead of the planned disclosure, and PHP pulled its release forward to 14:00 UTC on Wednesday. A couple of hours before the fix shipped, our clients already had detections for it running in production.
Nobody on our side had seen the bug yet. We didn't need to.
How the 48 hours played out
All times are UTC. The gap that matters is between the leak and the patch, because that is when every PHP server on the internet was exposed with nothing to install.
| When | What happened |
|---|---|
| Aug 2026 | Researchers at Calif, OpenAI and Wiz report the bugs to PHP. They stay under embargo while fixes are built. |
| Oct 17 | Amazon's MadPot honeypots log a PHP2Shell exploitation attempt, four days before disclosure. |
| Oct 20, morning | Details leak online ahead of the planned October 22 disclosure. watchTowr confirms the leak is genuine. |
| Oct 20, 19:33 | PHP's security team announces an emergency release for the next day at 14:00 UTC. |
| Oct 21, 07:43 | Cloudflare's CTO reports early attack attempts against PHP sites. |
| Oct 21, before 14:00 | The story lands in Soc0's Discover feed. Three detectors are generated, hunted and deployed for our clients. |
| Oct 21, 14:00 | PHP ships 8.5.12, 8.4.27, 8.3.36 and 8.2.35. |
| Oct 21 to 22 | Honeypots watch probes turn into web shells, download cradles and Mirai loaders. |
The bug, briefly
Researchers are calling it PHP2Shell, but it's really two separate memory-corruption bugs in the PHP engine. Both are rated 9.2 on CVSS v4.0. Both can be exploited over HTTP without authentication, and on mod_php the attack lands before any application code runs.
| CVE | PHP's description | What goes wrong |
|---|---|---|
| CVE-2026-109618 | RCE via OOM corruption | A request hits memory_limit partway through an allocation. PHP bails out and leaves half-built data behind, which request cleanup then trusts. |
| CVE-2026-109619 | RCE via stale global state | A fatal error skips teardown, so the worker keeps a pointer to freed memory. The next request on the same worker uses it. |
Both share a root cause. A fatal error interrupts PHP mid-operation, and PHP later treats the incomplete state as valid. Every runtime that serves HTTP is in scope, including PHP-FPM, Apache mod_php, php-cgi, FrankenPHP and LiteSpeed. Datadog Security Labs has the best technical breakdown so far.
These are old bugs. Calif says the out-of-memory flaw was first found in 2020 and rediscovered in a 2024 audit. Exploiting it took an exceptionally complex chain of steps, and Wiz says frontier AI models substantially reduced that barrier. Expect more of this: long-standing bugs that suddenly become cheap to weaponize.
Upstream fixes only cover PHP 8.2 through 8.5. Branches 7.4, 8.0 and 8.1 got minimal source backports meant for people who build PHP themselves. Mallory counted about 884,000 internet-facing hosts whose banners advertise PHP 8.1 or older.
Nothing to write a signature against
When the story broke, PHP's notice didn't say which component was affected, which versions, or what an attacker needed. You can't write an exploit rule for a bug nobody has described, and patching a big PHP estate takes days at best.
Even the basics were in flux. The leak claimed a CVSS score of 10.0, and PHP rated both bugs 9.2. Early coverage tied the session upload-progress path to the wrong CVE. Anyone building detection logic from the first wave of reporting was building on sand.
What you can watch is what happens after someone gets code execution on a PHP server. That part doesn't change much from one bug to the next.
You can't write an exploit rule for a bug nobody has described. You can write one for what attackers do the minute after it works.
What Soc0 did with a headline
The Hacker News story landed in Soc0's Discover feed soon after it went up, rated High severity with Medium source confidence. Soc0 read the report, picked out the post-exploitation activity it described, and turned that into three detector templates already mapped to each client's security products.

The summary was honest about what wasn't known. It flagged that the CVE IDs came from a leaked post, that PHP's own notice named no workaround or technical detail, and that end-of-life branches would get no vendor patch.
After that it was a matter of running a hunt over historical data and deploying. Nobody had to write SPL, KQL or XQL. The whole path looks like this:
- Discover. The article arrives in the feed, scored for severity, popularity and source confidence.
- Extract. Soc0 pulls out the attacker behavior the report describes, not the indicators.
- Map. Each behavior becomes a detector template, pre-parsed into the right query for whichever EDR or SIEM the client has connected.
- Hunt. The detector runs back over historical telemetry first, so you learn whether you were already hit before you start waiting for new alerts.
- Adopt. One click puts it into production.
The three detectors
1. Web server or PHP process spawning a shell
The first one looks for php-fpm, php-cgi, httpd or apache2 starting a shell or interpreter: sh, bash, cmd, PowerShell, Python or Perl. A PHP worker has almost no reason to do that, so when it happens, someone is usually running commands through it. Rated High.
If you want to build your own version, here is the logic as a Sigma-style sketch. Baseline the legitimate children in your environment first. PHP's exec() and system() run through sh -c, so apps that shell out to ImageMagick or Git will trip it.
title: Web server or PHP process spawning a shell
status: experimental
logsource:
category: process_creation
detection:
php_or_web_parent:
ParentImage|contains:
- '/php-fpm'
- '/php-cgi'
- '/httpd'
- '/apache2'
- '\php-cgi.exe'
- '\httpd.exe'
shell_child:
Image|endswith:
- '/sh'
- '/bash'
- '/dash'
- '/python3'
- '/perl'
- '\cmd.exe'
- '\powershell.exe'
- '\pwsh.exe'
condition: php_or_web_parent and shell_child
level: high2. Download or staging tool launched by PHP
The second catches PHP processes, or their children, running curl, wget, certutil, bitsadmin or Invoke-WebRequest. That's typically an attacker pulling down a second-stage payload. Also High.
3. New script written to the web root
The third watches for the web server or PHP worker writing .php, .phtml, .phar, .jsp or .aspx files into a web-accessible directory, which is how web shells get dropped. It's rated Medium because deploys and CMS updates do the same thing legitimately, so expect to tune it.
Then the attackers showed up and did exactly that
Within hours of the release, honeypot operators and researchers started publishing what exploitation looked like on the box. It lined up with the three detectors almost one to one.
| Seen after exploitation | Reported by | Detector that fires |
|---|---|---|
The public PoC running uname -a; id through the worker | ELLIO | 1. Shell from PHP |
apache2 (www-data) → sh -c → bash | Datadog, lab reproduction | 1. Shell from PHP |
curl calling out to attacker infrastructure, and a loader pulling a Mirai variant into /tmp | ELLIO | 2. Download tool |
<?php system($_GET["cmd"]); ?> dropped as .php, .phtml, .php5 and .php.jpg | ELLIO | 3. Script in web root |
ELLIO watched one address go from first probe to a working exploit in 48 minutes, and to an installed web shell 81 minutes after the probe. That is the window you get.
It's also why perimeter rules alone weren't enough. Cloudflare described its emergency WAF rules as temporary, and CrowdStrike found that after a successful hit, "the worker process does not crash, the server returns a standard HTTP 200 response, and application logs record nothing unusual." The dependable evidence was the process the worker started next.
Why behavior beats the CVE
None of these detections refer specifically to CVE-2026-109618. Behavior will catch a different adversary using a different vulnerability a different time.
The same three detectors would have fired on the follow-on activity from CVE-2024-4577, the PHP-CGI bug that drew exploit attempts within 24 hours of disclosure in 2024. They will fire on whatever PHP bug comes next. That is the core idea behind building detections that matter: aim at what the attacker has to do, not at the door they used.
Invest in detections that don't rely on a signature for a specific CVE.
Amazon Threat Intelligence, on PHP2Shell
The race is also getting shorter. When disclosure-to-exploit is measured in hours, and sometimes in negative days, a workflow that waits for a vendor signature loses by design. The workflow that wins already knows what post-exploitation looks like and only needs to be pointed at the new target.
If you run PHP
- Patch. Move to 8.5.12, 8.4.27, 8.3.36 or 8.2.35. On 8.1 or older, get a backport from your distribution or LTS vendor, or upgrade.
- Restart every worker. Running PHP-FPM pools and Apache children keep the old code in memory. Check the process actually serving requests, not just the package version, since backported builds can report the original version number.
- Hunt back to October 17. Amazon logged an exploitation attempt four days before disclosure. Run whatever detections you put in place back over your logs from then, not from the day the news broke.
- Watch the quiet tells.
Allowed memory size ... exhaustedfatals that endin Unknown on line 0, segfaulting Apache children, and POST bodies carryingPHP_SESSION_UPLOAD_PROGRESS. - If you can't patch today, narrow the paths. PHP published temporary settings that block the demonstrated routes. They are below.
; Temporary PHP2Shell mitigations. Not a fix: patch, then remove.
; php_admin_* stops applications from overriding these at runtime.
; CVE-2026-109619: close the session upload-progress path
php_admin_flag[session.upload_progress.enabled] = off
; CVE-2026-109619 on PHP 8.5: close the fatal-error backtrace path
php_admin_flag[fatal_error_backtraces] = off
; CVE-2026-109618: remove the memory_limit trigger
php_admin_value[memory_limit] = -1Next time
The next PHP2Shell is already sitting in someone's audit notes. When it leaks, the useful question won't be whether a signature exists yet. It will be whether you're already watching what attackers do once they're in.
That's the loop we built Soc0 to run: from article to applied detector in minutes, on the security stack you already have.
See Port0 on your own data.
Bring your noisiest alert queue. Watch Soc0 investigate it live.






