PHP2Shell: Timeline, Research Findings and What It Costs (CVE-2026-109618/109619)
The Nisura Team · · Updated
Written on 21 October 2026, the day PHP shipped the fixes. This is a fast-moving story; we'll date every update below.
Update, 22 October: Ubuntu and Debian have shipped fixed packages. If you run WordPress or any PHP site on your own Ubuntu or Debian server (a Hetzner cloud server, for example), you can patch now: see how to patch. Can't yet? See PHP's stopgaps.
Also on 22 October: exploitation is now confirmed in the wild — and it started before the fix shipped. Amazon reports an attempt four days ahead of disclosure; ELLIO logged automated payloads building through the evening of the 21st. If you haven't patched, treat your PHP servers as actively targeted.
PHP2Shell is the name for two critical flaws in PHP itself, CVE-2026-109618 and CVE-2026-109619, both rated CVSS 9.2. Details leaked a day before the planned disclosure, so for roughly 24 hours defenders, researchers, vendors and news outlets were all working from partial information, and they didn't always agree. This post puts the day in order: a timeline, what PHP confirmed, what each research team found, where the early analysis was wrong, and what the flaws are worth in euros while the usual risk scores were still blank.
The short version
- Patch the PHP runtime to 8.5.12, 8.4.27, 8.3.36 or 8.2.35, then restart Apache, PHP-FPM and any long-running PHP workers. That is the only complete fix (PHP).
- Updating WordPress, Drupal or Laravel does not fix it. The flaw is in PHP, and PHP processes the attack before any application code runs.
- Every web setup is affected: PHP-FPM, Apache mod_php, php-cgi, FrankenPHP and LiteSpeed. PHP rates mod_php the highest risk.
- PHP 8.1 and older get no release. PHP published source-code backports for 7.4, 8.0 and 8.1; your Linux distribution or hosting provider may ship them. Otherwise isolate or upgrade.
- Exploitation is confirmed, automated, and started early. Amazon says it caught an exploit attempt four days before the planned disclosure; ELLIO logged the first hit 5.5 hours before the fix was public, then a flood of automated payloads by nightfall. Yet on day one neither flaw was in the official exploited-vulnerability catalogs or carried an exploitation score.
Timeline
Times in UTC where a source gives one.
| When | What happened | Source |
|---|---|---|
| 17 Oct | Amazon Threat Intelligence records an exploit attempt against its MadPot honeypot — four days before the planned disclosure, from an anonymized IP. | Amazon, via THN |
| 20 Oct | Technical details leak online ahead of the coordinated disclosure. | Huntress |
| 20 Oct | PHP announces a critical security release for 21 Oct, 14:00 UTC: two flaws, CVSS v4.0 9.2, "prepare now". | php.net |
| 20 Oct | watchTowr confirms the leak is genuine and reproduces the flaws. | watchTowr |
| 21 Oct, 05:00 | GMO Flatt Security says the session.upload_progress setting it had suggested is not a complete fix. | The Hacker News |
| 21 Oct, 08:36 | ELLIO logs the first PHP2Shell request against its sensors — 5.5 hours before the fix is public; user agent php2shell-scan/109618. | ELLIO |
| 21 Oct, morning | Cloudflare reports early exploitation attempts; Patchstack receives "multiple active exploitation incidents" from hosting partners. | THN, Patchstack |
| 21 Oct | Cloudflare ships an emergency WAF release: seven blocking rules for anomalous request patterns. | Cloudflare |
| 21 Oct, 13:48 / 13:54 | PHP publishes both CVE records, with the affected version ranges. | CVE-2026-109618, -109619 |
| 21 Oct, 14:00 | PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 released with the advisory (GHSA-w8hw-w9fx-j79w, GHSA-6wmf-4rv5-p3rp). | php.net |
| 21 Oct, 14:00 | Huntress: no exploitation seen across its partner base so far. | Huntress |
| 21 Oct, 15:20 | CERT-EU advisory 2026-018: patch immediately, or isolate internet-facing applications until fixed. | CERT-EU |
| 21 Oct, 13:56 | Ubuntu USN-8948-1: fixed packages for Ubuntu 22.04, 24.04, 26.04 and 26.10. | Ubuntu |
| 21 Oct, 15:33 | Ubuntu USN-8948-2: fixes for 14.04, 16.04, 18.04 and 20.04, through Ubuntu Pro. | Ubuntu |
| 21 Oct | Debian fixes 12 (DLA-4848-1) and 13 (DSA-6574-1); AlmaLinux puts patched packages in testing. | Debian, AlmaLinux |
| 21 Oct, 16:05 → 20:40 | ELLIO: exploit-shaped requests for CVE-2026-109618 begin (16:05); by 20:40 a multi-vulnerability scanning bot has folded PHP2Shell into its run — payloads climb past 180/hour into the night. | ELLIO |
| 21 Oct, afternoon | Our check: neither CVE in CISA KEV (catalog 2026.10.21) or ENISA EUVD’s exploited list; no EPSS score yet. | KEV, EUVD, EPSS |
What PHP confirmed
PHP's advisory is the source of record, and it settled most of the early arguments:
- CVE-2026-109618: running out of memory can interrupt PHP while request data is only partly set up, and the cleanup then treats it as valid.
- CVE-2026-109619: state owned by one request can survive after its memory is freed, and a later request on the same worker may use it.
- Affected: all PHP installations serving web requests, with the highest risk on mod_php, where “an unauthenticated request can trigger the attack before any application code runs.”
- Stopgaps until you patch differ per flaw (listed below). PHP says they “reduce exposure to specific attack paths but do not make an installation safe.”
- 8.1 and older receive no release, but PHP published source backports for 7.4, 8.0 and 8.1.
What the researchers found
- Wiz Research demonstrated unauthenticated remote code execution against WordPress, Drupal and Joomla using their latest container images, plus application-agnostic memory disclosure. The flaw's official site says releases back to PHP 5.4 are affected by at least one of the issues.
- watchTowr was first to confirm the leak, reproduced both CVEs, and reports “active exploitation attempts of both.” Its FAQ calls configuration changes “ineffective and not suitable to prevent exploitation.”
- Datadog Security Labs has the most useful detection advice: watch for PHP workers spawning shells, and for large form submissions followed by memory-exhaustion errors. Successful exploitation need not crash the worker, which makes it hard to spot.
- Huntress stresses inventory first: find every PHP install, patch, and isolate end-of-life PHP from the internet.
- Patchstack relayed exploitation incidents from hosting partners and warned against unofficial “fix” plugins: the stopgaps “reduce exposure to specific attack paths but do not make an installation safe.”
- JFrog Security Research published an explainer of both flaws and the fixed versions.
- ELLIO published hour-by-hour telemetry from its deception network. The first probe, at 08:36 UTC, carried the
php2shell-scan/109618user agent and the CVE-2026-109619 session field together — so the tooling was built straight from the leak, not reconstructed from the patch. Volume stayed low until the release, then climbed past 180 payloads an hour after dark as a multi-vulnerability bot picked the flaws up. - Sansec predicted mass exploitation within minutes of the release (SecurityWeek); Aikido also reported exploitation (Security Boulevard).
Reactions from the PHP project
Asked whether the session setting would protect people, PHP core developer Gina Peter Banyard replied: “the only mitigation is patching / upgrading PHP.” Joe Ferguson, release manager for PHP 8.6, put it as “ini settings won't save you” (both reported by The Hacker News).
Where the early analysis went wrong
For about a day, credible-looking analysis circulated that PHP's advisory later contradicted. Worth remembering for the next leak:
| Early claim | Who said it | What PHP confirmed |
|---|---|---|
| Only Apache mod_php and the built-in server are affected; PHP-FPM, CGI and LiteSpeed are safe | independent write-up (J4ck3LSyN) | All web setups are affected; mod_php is the highest risk |
| One flaw is memory corruption only, not code execution | same write-up | Both flaws are rated remote code execution |
| Setting session.upload_progress.enabled=0 is the fix | social media, several blogs; one vendor still listed it as an immediate mitigation | A stopgap for one of the two flaws only; patching is the fix |
| The circulating public exploit code works | various posts | Not shown to work at the time; an anonymous audit said it did not fire against released PHP (THN) |
The lesson isn't that early researchers were careless. It's that before the vendor advisory, nobody outside the reporting team could test anything. Act on the vendor's advisory and your distribution's notice, not on the most detailed early write-up.
The version-number trap
If your PHP comes from Ubuntu or Debian packages, a patched server can still say PHP/8.3.6: distributions backport fixes into the version you already run. Judge by your distribution's advisory for your exact package, not the version string (THN). Hosting providers build their own packages after the upstream release; CloudLinux, for one, said its updates depend on it.
Patch now: Ubuntu and Debian fixes are out
PHP gave Linux distributions the patches in advance, and both major ones shipped on 21 October. If your PHP comes from your distribution's own packages, which is the default on a self-managed cloud server such as a Hetzner, DigitalOcean or OVH instance, this is the build to look for:
| Release | Package | Fixed version | Notice |
|---|---|---|---|
| Ubuntu 26.10 | php8.5 | 8.5.9-0ubuntu2.1 | USN-8948-1 |
| Ubuntu 26.04 LTS | php8.5 | 8.5.4-0ubuntu1.5 | USN-8948-1 |
| Ubuntu 24.04 LTS | php8.3 | 8.3.6-0ubuntu0.24.04.13 | USN-8948-1 |
| Ubuntu 22.04 LTS | php8.1 | 8.1.2-1ubuntu2.28 | USN-8948-1 |
| Ubuntu 20.04 (Ubuntu Pro) | php7.4 | 7.4.3-4ubuntu2.29+esm5 | USN-8948-2 |
| Debian 13 | php8.4 | 8.4.27-1~deb13u1 | DSA-6574-1 |
| Debian 12 | php8.2 | 8.2.35-1~deb12u1 | DLA-4848-1 |
Older Ubuntu releases (14.04 to 18.04) are fixed through Ubuntu Pro as well; see Ubuntu's CVE page. On Ubuntu 24.04, the steps look like this (swap 8.3 for your branch):
# 1. Is the fixed build on your mirror yet? "Candidate" is what apt would install.
sudo apt update
apt-cache policy php8.3-fpm
# 2. Upgrade only the PHP packages you already have, nothing else
sudo apt install --only-upgrade $(dpkg-query -W -f='${Package}\n' 'php8.3*' 'libapache2-mod-php8.3')
# 3. Restart everything that runs PHP: a running worker keeps the old code
sudo systemctl restart php8.3-fpm
sudo systemctl restart apache2 # if you also use mod_php
# 4. Check the package revision; php -v still says 8.3.6, and that is normal
dpkg -l | grep -E '^ii +(php8\.3|libapache2-mod-php8\.3)'We ran this on a Ubuntu 24.04 server of ours at Hetzner hosting five WordPress sites, with PHP-FPM and mod_php both in use. Three things we noticed:
- A notice isn't the same as your mirror. Hours after USN-8948-1, the server still offered the old
…24.04.12build. Check theCandidateline before you assume you can patch; the Hetzner mirror caught up the same day. - Automatic security updates may have beaten you to it. Ubuntu installs security updates on its own by default. When we ran step 2, the fixed build was already installed (“0 upgraded”). We restarted FPM and Apache anyway, to be sure the running workers had loaded it.
- We kept the upgrade targeted. A full
apt upgradeworks too, but on a production box with held packages (nginx and Docker, in our case) we patched PHP only.
Not covered by these packages: PHP from a third-party repository (such as a PPA), PHP builds that come with a control panel (Plesk, cPanel, FastPanel, CloudLinux alt-php), and PHP inside containers. Each updates through its own source: the panel or vendor, or a rebuild from a fixed image. A panel's end-of-life branch (PHP 7.4, say) gets no fix unless the vendor ships a backport; upgrade it or take it off the internet. On managed WordPress hosting, your host patches; check its status page.
Not sure what you run? Paste your package list into our free PHP2Shell checker; it judges Ubuntu and Debian builds on the distribution's own fix data.
Can't patch yet: PHP's stopgaps
PHP's advisory lists measures for the time before you can update. It is explicit that they only “reduce exposure to specific attack paths,” and each covers one of the two flaws, so apply both sets. Set them where applications can't override them (php.ini, the FPM pool, or the Apache configuration), then restart every PHP worker.
| Flaw | Stopgap | What it does not cover |
|---|---|---|
| 109618 (OOM corruption) | memory_limit=-1, set with php_admin_value, and check no pool, directory or app puts a finite limit back | Removes the memory-limit failure an attacker can steer, but a genuine allocation failure can still reach the flaw. |
| 109618 | Low post_max_size: 8M without uploads, 32M with; keep upload_max_filesize below it | PHP also suggests web-server or proxy limits on request size, field and multipart counts, headers and nesting, including for requests without a usable Content-Length. |
| 109618 | A container or cgroup memory limit that kills only the affected worker | An availability boundary, not a fix. Don't use RLIMIT_AS or RLIMIT_DATA instead: they can cause the vulnerable failure. |
| 109619 (stale state) | session.upload_progress.enabled=0 in php.ini, the FPM pool or server config | Blocks the confirmed session paths, not other variants. ini_set() and FPM .user.ini apply too late. |
| 109619, PHP 8.5 | fatal_error_backtraces=0 | Blocks the confirmed fatal-backtrace path only. |
| 109619 | Remove invalid or deprecated per-request settings that emit warnings early; fix fatal errors and timeouts an attacker can trigger | Hiding the warnings with error_reporting, display_errors or @ doesn't help. |
memory_limit=-1 sounds backwards: it lets one request use as much memory as the server has. That is why it belongs with the container or cgroup limit, so a runaway request takes down one worker, not the box. The more useful stopgap is often simpler: restrict who can reach the site (a firewall or Cloudflare in front, an allowlist), as CERT-EU advises, until you can patch. Once you have, the stopgaps can stay or go; PHP says only the update is a complete solution.
Can you tell from outside whether a site is affected?
Rarely. To test it, we made one ordinary homepage request to each of 14 European company domains we use as a fixed test set (13 answered). None showed its PHP version. Four clearly run PHP (three WordPress, one TYPO3), so the honest outside verdict for them is “PHP in use, version hidden: check it yourself.” Only a server that advertises its version can be judged from outside, and for distribution builds even that needs the distribution's own data. The reliable check is on the server: the PHP version that serves web requests, and your package against your distribution's advisory.
Your own logs don't help much either. CrowdStrike says a successful hit leaves “no authentication to bypass, no session to steal, and no vulnerable endpoint to discover”: workers stay up, responses return HTTP 200, and the only server-side trace is a single memory-limit fatal in the error log, easily dismissed as noise (reported by THN). With exploitation this quiet and the outside view this blind, the one unambiguous check is the PHP build your server actually runs. Paste your package list into our free PHP2Shell checker — it judges Ubuntu and Debian builds against the distribution's own fix data, so you get a verdict without waiting for a scanner or a log to tell you.
What it costs while the scores are blank
Risk models lean on EPSS, FIRST's probability that a CVE is exploited in the next 30 days. On 21 October neither PHP2Shell CVE had an EPSS score, and neither was in the KEV or EUVD exploited lists, while vendors were already reporting attacks. To show what that gap means, we ran our engine for a fictional company: an Austrian manufacturer with 120 staff, €20M revenue, MFA and EDR, and one internet-facing PHP server affected by both CVEs. A breach would cost it €728,464 (downtime, lost margin, forensics and NIS2 exposure).
| Exploitation probability assumed | Annual likelihood | Expected annual loss |
|---|---|---|
| Without PHP2Shell (baseline) | 2.24% | €16,318 |
| 1% (our engine’s floor while a CVE is unscored) | 2.34% | €17,081 |
| 10% | 3.29% | €23,935 |
| 50% | 7.41% | €53,994 |
| 99.99% (today’s EPSS for CVE-2024-4577, 2024’s PHP-CGI flaw) | 12.44% | €90,638 |
These are scenarios, not forecasts: FIRST hadn't scored these CVEs, so we show the range instead of inventing a number. The same server is worth €17,000 or €91,000 of expected loss depending on a score that didn't exist on day one. That gap, between a live attack and the data risk models wait for, is exactly what a quantified view has to handle.
EU obligations to keep in mind
- CERT-EU advises patching immediately, or isolating internet-facing applications until a fix is applied and verified.
- Under NIS2, Article 21 expects vulnerability handling as part of risk management, and a significant incident triggers the Article 23 early warning within 24 hours.
- The memory disclosure can expose passwords, session tokens and API keys. If personal data is affected, GDPR Article 33 requires notifying your authority within 72 hours.
Checklist
- Inventory every PHP runtime: servers, containers, staging, hosted sites. Not sure what a box runs? Our PHP2Shell checker reads a pasted package list.
- Patch to 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35, or install your distribution's fixed package (table above); restart Apache, PHP-FPM and workers.
- Check the version on the process that serves web traffic, not
php -vin a shell. - Can't patch yet: restrict who can reach the site (firewall, VPN, allowlist), applyPHP's stopgaps for both flaws, and reduce what a compromised server can reach.
- PHP 8.1 or older: get a backported build from your vendor, upgrade, or take it offline.
- Look back: PHP workers spawning shells, large uploads followed by memory errors, new web shells or cron jobs (Datadog, watchTowr).
All sources
- Official: PHP security advisory; PHP advance notice; CVE-2026-109618; CVE-2026-109619; CERT-EU advisory 2026-018; php2shell.com.
- Research: Wiz; watchTowr and FAQ; Datadog Security Labs; Huntress; JFrog; Patchstack; ELLIO; J4ck3LSyN.
- Vendors and distributions: Cloudflare WAF release; Ubuntu USN-8948-1 and USN-8948-2; Debian security tracker; AlmaLinux; CloudLinux.
- Reporting: The Hacker News (disclosure); The Hacker News (what protects you); The Hacker News (exploitation in the wild); SecurityWeek; Security Boulevard.
- PHP project: Gina Peter Banyard; Joe Ferguson.
- Catalogs we checked: CISA KEV; ENISA EUVD; FIRST EPSS.
We don't link exploit code. New to putting a number on this kind of risk? Start with what cyber risk quantification is.
Frequently asked questions
Which PHP versions fix PHP2Shell?
PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35, released on 21 October 2026. PHP 8.1 and older receive no release; PHP published source-code backports for 7.4, 8.0 and 8.1, which Linux distributions or hosting providers may ship. Restart Apache, PHP-FPM and long-running workers after updating.
Does updating WordPress, Drupal or Joomla fix PHP2Shell?
No. The flaws are in the PHP runtime, and PHP processes the attack before any application code runs. Only updating PHP itself (or installing your distribution’s fixed package) fixes it.
Does session.upload_progress.enabled=0 protect me?
Only partly. PHP lists it as a stopgap for CVE-2026-109619 only, and even there it blocks the confirmed session paths, not other variants. CVE-2026-109618 needs different stopgaps (memory_limit=-1 set so apps can’t override it, a low post_max_size, and a container or cgroup memory limit). PHP says only updating is a complete solution.
Is there an Ubuntu or Debian fix for PHP2Shell?
Yes, since 21 October 2026. Ubuntu USN-8948-1 fixes 22.04, 24.04, 26.04 and 26.10 (on 24.04 the fixed build is php8.3 8.3.6-0ubuntu0.24.04.13), and USN-8948-2 covers 14.04 to 20.04 through Ubuntu Pro. Debian fixes 12 (php8.2 8.2.35-1~deb12u1) and 13 (php8.4 8.4.27-1~deb13u1). Upgrade the PHP packages, restart PHP-FPM and Apache, and check the package revision with dpkg -l.
My Ubuntu server still says PHP 8.3.6 after updating. Am I patched?
Possibly. Ubuntu and Debian backport security fixes without changing the upstream version number, so check your exact package version against your distribution’s advisory or the package changelog rather than the version string.