Blog - Latest News
Median vulnerability life span by weakness class

PHP2Shell: what a runtime zero-day teaches us about patch readiness

On 21 October 2026 the PHP project shipped emergency releases for two critical flaws now known as PHP2Shell. Under the right conditions, both let an unauthenticated attacker run code on a server running PHP.

My team had everything patched within hours. That was not luck, and it was not heroics. It came from boring things done well beforehand: tidy architecture, clear ownership, documented environments, automation, and knowing what we run, where it runs and how to update it safely.

This post walks through what happened, why a bug in the runtime walks straight past your application’s login page, what the research says about exposure windows and patch speed, and a checklist you can use before the next one lands.

What happened

The PHP Foundation describes two related remote code execution (RCE) vulnerabilities [S1]:

  • CVE-2026-109618, RCE via out-of-memory corruption. If a request hit PHP’s memory_limit at exactly the wrong moment, PHP could leave partially initialised internal data behind and later treat it as valid. On Apache with mod_php, an unauthenticated request can trigger this before any application code runs.
  • CVE-2026-109619, RCE via stale global state. A fatal error at the wrong point could leave internal state pointing at memory from a previous request. A later request handled by the same worker could then use that freed memory. This is a use-after-free.

The fixed releases are PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 [S1]. Each CVE carries a CVSS v4.0 score of 9.2 [S1, S3, S4].

The scope is wide. CISA says the flaws affect all PHP installations serving web requests, including Apache with mod_php (which PHP considers highest risk), PHP-FPM, php-cgi, FrankenPHP and LiteSpeed [S2].

Older branches are affected too. PHP 8.1 and earlier get no official release, but the PHP security team did publish minimal source backports for 7.4, 8.0 and 8.1 [S3, S4]. Anything older, including PHP 5, has no fix at all [S4]. If you are on those versions, you depend on your distribution or long-term support vendor, or you upgrade.

The disclosure itself did not go to plan. The CVE IDs began circulating online on 20 October, around 15:00 UTC, with a wrong release time and a wrong CVSS score of 10.0 [S1]. PHP brought the release forward by a day. A reporting firm then mistakenly published a proof-of-concept video, and one distributor published patched images more than six hours before the coordinated release [S1].

On exploitation, the sources differ, which is normal in the first days of an incident. Datadog reports that AWS saw exploitation attempts as early as 17 October, four days before disclosure [S3]. watchTowr observed exploitation in its honeypots from 21 October [S4]. CISA, at the time of its alert, had not observed successful exploitation [S2], and as of 22 October neither CVE was on CISA’s Known Exploited Vulnerabilities list [S4].

One point is consistent across every source: configuration changes do not fully fix this. Datadog warns that mitigations circulating in the community “don’t fully protect you” [S3]. watchTowr notes that PHP itself says no configuration change fully mitigates the flaws [S4]. Patching is the only complete fix.

Why runtime-level RCE gets past your login page

Most of us think about security at the application layer. Is the user authenticated? Is the input validated? Is the query parameterised?

PHP2Shell sits below all of that. Datadog reproduced CVE-2026-109618 with a single unauthenticated HTTP POST request that never reached the target application’s code [S3]. PHP ran the attacker’s command while it was cleaning up the failed request. Any PHP script exposed the vulnerable path, even one that only prints a response [S3].

Here is the order of events. PHP receives the request and parses the form body into $_POST before your code runs. During that parsing, an allocation fails at a carefully chosen moment. A hash table has already counted a new entry but never filled it in. When PHP tears the request down, it treats leftover bytes as a real value, and an attacker who controls those bytes controls what happens next [S3].

Your authentication check never gets a vote. Neither does your input filtering.

This is a textbook memory-safety problem. In their survey of memory corruption, Szekeres and colleagues describe how an attacker first makes a pointer invalid and then gets the program to use it [R1]. A pointer to freed memory is a dangling pointer, and using one is a temporal error. They even name an unchecked allocation failure as one way a pointer goes bad [R1]. PHP2Shell is a modern example of exactly those two classes: half-built data after an allocation failure, and a use-after-free across requests.

Research also tells us these bugs hide for a long time. Li and Paxson studied more than 3,000 vulnerabilities across 682 open-source projects. Web bugs like SQL injection and cross-site scripting had median life spans in the code of 230 and 290 days. Buffer overflows sat there for a median of 781 days [R4]. The PHP Foundation’s own account fits that pattern: the first signs of the out-of-memory problem were found in 2024, and the fix stalled for months before researchers showed the full impact in 2026 [S1].

Median vulnerability life span by weakness class
Chart 1. Median days a vulnerability existed in the code base before it was fixed, top 10 CWE classes. Source: Li and Paxson (2017), Table 3 [R4].

The lesson: a runtime is shared plumbing. One flaw in it is a flaw in every application on top of it, no matter how carefully each application was written.

What research says about exposure windows and patch speed

Zero-days last longer than you think

Bilge and Dumitraș searched field data from 11 million hosts for attacks that exploited vulnerabilities before disclosure. They found 18 such vulnerabilities, 11 of which were not previously known to have been zero-days. Those attacks lasted between 19 days and 30 months, with a median of 8 months and an average of 312 days [R2].

The more important finding for defenders is what happens after disclosure. The number of attacks rose by between 2 and 100,000 times, an increase of up to five orders of magnitude [R2]. Exploits for 42% of vulnerabilities used in host-based threats were seen in field data within 30 days of disclosure [R2].

Disclosure is when the race starts. Everyone now knows where to look, including the attackers.

The patch often exists before the advisory

Li and Paxson found that over 50% of the vulnerabilities they studied were patched in the public repository more than a week before public disclosure [R4]. Attackers who watch repositories can get a head start of weeks to months [R4]. PHP2Shell had a binary version of the same problem: once patched images were public early, anyone could study the fix while everyone else waited [S1].

They also found that patches are not always right the first time. They estimate about 7% of security fixes were incomplete and about 5% introduced new problems [R4]. That is a good reason to test rollouts and keep a rollback path, even in an emergency.

Frei and colleagues, analysing more than 80,000 security advisories, set out to measure the gap between when exploits and patches become available [R5]. Shahzad, Shafiq and Liu’s study of 46,310 vulnerabilities disclosed between 1988 and 2011 examines the phases of that same life cycle [R6]. The details vary by era and data set, but the shape is consistent: attackers move quickly once a flaw is public.

Deployment is the slow part

Writing a patch is one step. Getting it onto every running system is another.

Nappa and colleagues followed patch deployment for 1,593 vulnerabilities on 8.4 million hosts over five years [R3]. The median time to patch half the vulnerable hosts was 45 days. When exploits were released, the median fraction of vulnerable hosts already patched was at most 14% [R3].

Two of their findings map neatly onto PHP2Shell. First, who manages the system matters. Hosts belonging to security analysts patched half their population in a median of 18 days, and software developers in 24 days, compared with 45 days for general users [R3]. Second, shared code causes trouble. When the same vulnerable code shipped in two applications, the patches arrived up to 118 days apart, with a median of 11 days [R3]. That is what happens when PHP hides inside an appliance or a vendor image and waits for someone else’s release cycle.

Median time to patch half of vulnerable hosts
Chart 2. Median days to patch 50% of vulnerable hosts, by user group. Source: Nappa et al. (2015) [R3].

Heartbleed showed the same thing on servers. Durumeric and colleagues found that all but 5 of the Alexa Top 100 sites patched within 24 hours [R7]. But the overall picture was a fast start followed by a plateau. Between 9 April and 4 June 2014, the vulnerable share of the Alexa Top 1 Million fell from 11.5% to 3.1%, and for all HTTPS hosts from 6.0% to 1.9% [R7]. The researchers identified over 70 models of vulnerable embedded devices and software packages, and in one later scan embedded devices made up 56% of vulnerable hosts, many with no obvious way for administrators to patch them [R7]. Notifying operators directly produced a nearly 50% increase in patching [R7].

Heartbleed vulnerable share in April and June 2014
Chart 3. Share of hosts still vulnerable to Heartbleed, 9 April and 4 June 2014. Source: Durumeric et al. (2014) [R7].

The long tail is where breaches live. Teams who know their estate patch in the first wave. Systems nobody owns stay vulnerable for months.

Prioritise by likely exploitation, not only severity

A CVSS score of 9.2 tells you how bad a flaw could be. It does not tell you how likely it is to be used against you.

Allodi and Massacci found that fixing a vulnerability just because it has a high CVSS score is, in their words, equivalent to randomly picking vulnerabilities to fix. A public proof of concept was a much better risk signal, and exploits in black markets better still [R8]. The Exploit Prediction Scoring System (EPSS) turns that idea into a model. It estimates the probability that a vulnerability will be exploited in the wild within 12 months of disclosure [R9]. A later version, built with input from more than 170 experts, reported an 82% performance improvement over earlier models [R10].

For PHP2Shell, every signal pointed the same way: critical score, public proof of concept, reports of attempts in the wild, and a component on almost every web server. That combination is the top of any queue.

Web software is a big, popular target

Vasek, Wadleigh and Moore studied around 200,000 web servers. Servers running popular content management systems such as WordPress and Joomla were more likely to be hacked than those running none, and a CMS’s market share was positively linked with compromise [R11]. Their results also carry a warning against easy assumptions. Surprisingly, outdated software was not more likely to be compromised in their data, and fewer than 5% of hacked WordPress sites were later updated [R11].

PHP itself has been a research subject for a long time. Jovanovic, Kruegel and Kirda built Pixy, a static analysis tool for finding vulnerabilities in PHP applications, back in 2006 [R12]. Tools like that focus on application code. PHP2Shell is a reminder that the runtime underneath needs the same attention.

A practical readiness checklist

None of this is new advice. What matters is having it in place before the advisory lands.

1. Know every place PHP runs

CISA’s first action was to identify and inventory every system running any version of PHP, and it warns that PHP is often a component of other software and may not be directly visible [S2]. Google Cloud adds that edge, gateway, management, storage and security systems frequently embed PHP in their control planes [S5]. Datadog reminds us to include containers and applications that bundle their own interpreter, and not to trust the command-line php -v, because it can differ from the runtime serving web traffic [S3].

So your inventory needs to cover:

  • Hosts and virtual machines with PHP packages.
  • Container images and base images, including ones built by other teams.
  • Appliances, admin consoles and vendor products that ship PHP inside.
  • Marketplace images and hosted platforms where you still own the image.

For each one, record the version, the package or image source, the owner and the update process [S3].

A software bill of materials (SBOM) helps here, but it is not magic. Xia and colleagues interviewed and surveyed SBOM practitioners and found open challenges remain, including in consuming and sharing SBOMs [R13]. Dependencies also drift. Kula and colleagues found 81.5% of the systems they studied still kept outdated dependencies [R14]. Generate SBOMs, but check them against what is actually running.

2. Patch internet-facing systems first

CISA tells organisations to patch immediately and prioritise internet-facing systems [S2]. watchTowr suggests starting with servers that run PHP as an Apache module [S4], which PHP considers highest risk [S2].

Have a ready-made, ranked list of internet-facing PHP services before you need it. That list is the difference between hours and days.

3. Use a WAF or reverse proxy as a stopgap, not a fix

CISA says a web application firewall may provide some protection until systems are patched [S2]. Datadog notes that controls at a reverse proxy in front of PHP can block requests before they reach the vulnerable parser [S3]. Google Cloud lists practical edge controls, such as blocking multipart uploads on routes that don’t need them and capping request body size [S5].

Treat all of this as buying time. Datadog warns that a rule can’t inspect bytes its engine truncates or bodies it handles differently [S3], and every source says only patching fully fixes the flaws.

4. Have a plan for unsupported versions

CISA’s advice for anything that can’t be updated, including PHP 8.1 and earlier, is to take it offline until it can be patched or upgraded [S2]. That is a hard call to make in the middle of an incident. Make it ahead of time by keeping a list of unsupported runtimes and an agreed plan for each.

Research on patch management backs this up. Dissanayake and colleagues reviewed 72 studies and found that patching is a socio-technical process with many stakeholders, and that only 20.8% of the solutions reported had been rigorously evaluated in industry [R15]. Process and people matter as much as tooling.

5. Watch for PHP workers spawning shells

CISA recommends monitoring for PHP worker processes launching shells or downloading tools [S2]. Datadog calls a web worker spawning a shell “the most direct evidence of successful exploitation” [S3]. It also warns that a successful exploit can return HTTP 200 without crashing the worker, so don’t rely on error rates [S3].

Practical signals to alert on:

  • sh, bash, curl or wget started by php-fpm, apache2, httpd or frankenphp [S5].
  • Memory exhaustion errors reported “in Unknown on line 0”, which means PHP failed before any script ran [S3].
  • Unusually long or binary PHPSESSID cookie values in responses [S3, S5].

If a host looks compromised, Google Cloud advises capturing worker memory before you restart it, because a restart destroys the evidence [S5].

6. Test the rollout, and the rollback

Updating the package on disk is not enough. Google Cloud points out that running workers keep the old binary in memory until you restart the actual web-serving process [S5]. Datadog’s steps include rebuilding and redeploying container images and replacing every worker still on the old runtime [S3].

Given Li and Paxson’s finding that some security fixes are incomplete or cause regressions [R4], your pipeline should let you:

  • Build a patched image or package automatically.
  • Deploy to a small slice first, check health, then roll out widely.
  • Roll back quickly if something breaks.
  • Verify afterwards that every running worker reports the fixed version.

Conclusion

PHP2Shell was serious because of where it lived. A flaw in memory handling and error handling, parts of PHP that nearly every request touches [S1], turned into code execution before any application logic ran.

The research has been telling us the same story for over a decade. Zero-days live for months before anyone notices [R2]. Attacks surge once a flaw is public [R2]. Patching starts fast and then stalls in a long tail [R3, R7]. Severity alone is a weak guide to what will be exploited [R8, R9].

You can’t control when the next runtime zero-day lands. You can control how ready you are. Tidy architecture, clear owners, documented environments, automated builds and a real inventory turn an emergency into a routine change. That is how my team patched in hours, and it is something any team can build.

Sources

Incident sources

Research references

  • [R1] Szekeres, L., Payer, M., Wei, T. and Song, D. (2013). SoK: Eternal War in Memory. IEEE Symposium on Security and Privacy, 48 to 62. doi:10.1109/SP.2013.13
  • [R2] Bilge, L. and Dumitraș, T. (2012). Before We Knew It: An Empirical Study of Zero-Day Attacks in the Real World. ACM CCS, 833 to 844. doi:10.1145/2382196.2382284
  • [R3] Nappa, A., Johnson, R., Bilge, L., Caballero, J. and Dumitraș, T. (2015). The Attack of the Clones: A Study of the Impact of Shared Code on Vulnerability Patching. IEEE Symposium on Security and Privacy, 692 to 708. doi:10.1109/SP.2015.48
  • [R4] Li, F. and Paxson, V. (2017). A Large-Scale Empirical Study of Security Patches. ACM CCS, 2201 to 2215. doi:10.1145/3133956.3134072
  • [R5] Frei, S., May, M., Fiedler, U. and Plattner, B. (2006). Large-Scale Vulnerability Analysis. SIGCOMM Workshop on Large-Scale Attack Defense, 131 to 138. doi:10.1145/1162666.1162671
  • [R6] Shahzad, M., Shafiq, M. Z. and Liu, A. X. (2012). A Large Scale Exploratory Analysis of Software Vulnerability Life Cycles. ICSE 2012, 771 to 781. doi:10.1109/ICSE.2012.6227141
  • [R7] Durumeric, Z. et al. (2014). The Matter of Heartbleed. ACM Internet Measurement Conference, 475 to 488. doi:10.1145/2663716.2663755
  • [R8] Allodi, L. and Massacci, F. (2014). Comparing Vulnerability Severity and Exploits Using Case-Control Studies. ACM Transactions on Information and System Security, 17(1). doi:10.1145/2630069
  • [R9] Jacobs, J., Romanosky, S., Edwards, B., Adjerid, I. and Roytman, M. (2021). Exploit Prediction Scoring System (EPSS). Digital Threats: Research and Practice, 2(3). doi:10.1145/3436242
  • [R10] Jacobs, J., Romanosky, S., Suciu, O., Edwards, B. and Sarabi, A. (2023). Enhancing Vulnerability Prioritization: Data-Driven Exploit Predictions with Community-Driven Insights. IEEE EuroS&P Workshops, 194 to 206. doi:10.1109/EuroSPW59978.2023.00027
  • [R11] Vasek, M., Wadleigh, J. and Moore, T. (2016). Hacking Is Not Random: A Case-Control Study of Webserver-Compromise Risk. IEEE Transactions on Dependable and Secure Computing, 13(2), 206 to 219. doi:10.1109/TDSC.2015.2427847
  • [R12] Jovanovic, N., Kruegel, C. and Kirda, E. (2006). Pixy: A Static Analysis Tool for Detecting Web Application Vulnerabilities. IEEE Symposium on Security and Privacy. doi:10.1109/SP.2006.29
  • [R13] Xia, B., Bi, T., Xing, Z., Lu, Q. and Zhu, L. (2023). An Empirical Study on Software Bill of Materials: Where We Stand and the Road Ahead. ICSE 2023, 2630 to 2642. doi:10.1109/ICSE48619.2023.00219
  • [R14] Kula, R. G., German, D. M., Ouni, A., Ishio, T. and Inoue, K. (2018). Do Developers Update Their Library Dependencies? Empirical Software Engineering, 23(1), 384 to 417. doi:10.1007/s10664-017-9521-5
  • [R15] Dissanayake, N., Jayatilaka, A., Zahedi, M. and Babar, M. A. (2022). Software Security Patch Management: A Systematic Literature Review of Challenges, Approaches, Tools and Practices. Information and Software Technology, 144, 106771. doi:10.1016/j.infsof.2021.106771
0 replies

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *