Skip to content
Security

PHP2Shell: what to do this week about the two PHP flaws patched on 21 October

·9 min read

On 21 October 2026 the PHP project shipped an out-of-band security release for two critical flaws in the PHP engine itself: CVE-2026-109618 and CVE-2026-109619, together nicknamed PHP2Shell. They are not bugs in WordPress, Laravel or your own code. They are in the runtime underneath all of them, so a clean application on an unpatched PHP is still exposed.

This note is for you if you run, host or are responsible for anything written in PHP and need to decide what to do this week. Everything below is as of 22 October 2026, and every claim links to its source at the end. The story is moving fast. Check the sources before acting on anything time-sensitive.

The short version

  • Fixed releases: PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35. Anything earlier on those branches is vulnerable.
  • Affected range: the PHP project and Google put it at 5.4 through 8.5.11, so roughly every PHP release since 2012.
  • PHP 8.1 and older get no new official release. Your fix there comes from your Linux distribution or an LTS vendor, or from upgrading to 8.2 or later.
  • Severity: 9.2 (Critical, CVSS 4.0) from the PHP security team, with no login and no user interaction needed.
  • Exploitation: attempts were seen before and on release day. CISA had not listed either CVE as known-exploited when we checked. Working attacks against a default install have not been shown publicly.
  • Patching is the only complete fix. The workarounds reduce exposure; they do not close it.
Cover page of PHP2Shell: Assessment & Action PlanFree PDF · 13 pagesPHP2Shell: Assessment & Action PlanThe full version of this note as a PDF to hand to whoever runs your servers: severity decoded, a dated exploitation timeline, exposure by deployment, a per-host patch procedure, compensating controls with their costs, a hunting checklist and a definition of done.Download the PDF →

What the two bugs actually are

CVE-2026-109618 ("RCE via OOM corruption"). When PHP runs out of memory, it aborts the request by jumping straight out of the code that was running. If that happens while internal request data is only partly set up, the cleanup that follows can read or act on data that was never valid. The PHP advisory says this can lead to remote code execution. Malformed multipart uploads are one way to push a request into that state: a missing content length, an unlimited number of part headers, or empty file fields.

CVE-2026-109619 ("RCE via stale global state"). PHP can keep internal state, such as error, session or extension state, pointing at memory that belonged to a request that has already finished. When the same worker process picks up the next request, some code runs before that state is reset and can read the freed memory, a classic use-after-free. The advisory names two confirmed paths. One is PHP 8.5's fatal-error backtraces. The other is session upload-progress handling. For this one to work, the attacker's two requests have to land on the same worker.

In plain terms, the first bug can corrupt memory within one request, and the second can carry corruption from one request into the next. Researchers chained them to get code execution.

Who is exposed

The PHP project's position is that every installation serving web requests is at risk: PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed. Risk is highest with mod_php, where a demonstrated exploit fires from an unauthenticated request before any of your application code runs.

Researchers have confirmed pre-authentication code execution against specific versions of WordPress, Drupal, Joomla and Magento. That is not the full list. Those platforms are named because they are the ones people tested first.

Places PHP hides that teams forget to count:

  • Container images you built yourself. Rebuilding on the same base image tag may not pull a patched PHP.
  • Managed platforms that do not patch automatically. On Google Cloud, App Engine flexible must be redeployed, and Cloud Run is patched only if automatic base-image updates are switched on. Other clouds have similar splits.
  • Hosting control panels, admin tools and vendor appliances with PHP inside. Check each vendor's advisory. Fortinet and F5 have already published theirs.
  • Old internal tools on 7.x that nobody owns, which are exactly the ones with no upstream fix.

How bad is it, really?

This is where the early coverage disagreed, so here is each position and where it came from.

Severity. The PHP security team rates both bugs 9.2 under CVSS 4.0. Its vector marks attack complexity as high and says attack prerequisites are present. That is critical, but not trivial. CVE IDs that circulated before release carried a 10.0, which the PHP Foundation says was incorrect. Some vendors quote 9.8 under the older CVSS 3.1. Several early summaries, including the first internal draft of this note, called exploitation low-complexity. The official vector says otherwise.

Exploitation. Amazon Threat Intelligence saw an attempt against its honeypots on 17 October, four days before disclosure, and further attempts from what looked like multiple actors on 21 October. Cloudflare reported early attacks on the morning of 21 October, hours before the 14:00 UTC release. watchTowr reports exploitation attempts against both bugs. On the other side, CISA's alert said it had not observed exploitation when it published. Neither CVE was in CISA's Known Exploited Vulnerabilities catalog (version 2026.10.21) when we checked it on 22 October.

Working exploits. The PHP security team found no functional exploits at release. On 22 October Sansec revised its view to say mass exploitation now looks less likely: the public proof-of-concept code it examined does not work against a default PHP install, and most of it needs a separate file-inclusion bug in the target application. Some exploit code circulating has not been verified and may contain malware. Do not run it to test yourself.

Attempts are real; reliable mass exploitation has not been shown. That is a reason to patch on a plan, starting today with whatever faces the internet. It is not a reason to wait.

One recommendation deserves weight because it changes what you look for. Amazon advises starting any investigation from 17 October, not from the disclosure date. If an internet-facing PHP server stayed unpatched over that period, look at its logs from then onwards.

Step 1 — Find out which version you are actually running

This is the step most likely to give you a false answer. Debian, Ubuntu, Red Hat and others backport security fixes into their existing packages without changing the version number. php -v can report 8.1.2 on a fully patched Ubuntu server and 8.3.20 on an unpatched one. Read the package changelog, not the version string:

# Version as reported (useful, but not proof either way on distro packages)
php -v

# Debian / Ubuntu: is the fix in the installed package?
zgrep -l CVE-2026-109618 /usr/share/doc/php*-common/changelog.Debian.gz

# RHEL / Alma / Rocky / Fedora
rpm -q --changelog php-common | grep -E 'CVE-2026-10961(8|9)'

# Containers: check the image that is running, not the Dockerfile
docker exec <container> php -v

Check what the web server uses, not what the command line uses. PHP-FPM and the CLI can be different binaries with different configuration. Confirm the version and settings from a request served through FPM, for example a phpinfo() page on localhost that you delete straight afterwards.

Step 2 — Patch, then restart every worker

  • On 8.2 to 8.5: upgrade to 8.2.35, 8.3.36, 8.4.27 or 8.5.12, or install your distribution's patched package.
  • On 7.4 to 8.1: use your distribution's or LTS vendor's backported package if you have one. The PHP security team has published minimal source backports for these branches but will not cut releases. Plan the move to 8.2 or later regardless.
  • On 5.4 to 7.3: there is no fix from the PHP project. Upgrade, isolate, or pay for an extended-support vendor.
  • Restart PHP-FPM, Apache and any long-running PHP worker. A patched binary on disk does nothing for a process that loaded the old one.
  • Rebuild container images from a patched base and redeploy. Then check the running image, not the build log.

Step 3 — If you cannot patch today

CISA's advice is blunt: if you cannot patch right away, or you run PHP 8.1 or earlier, take the PHP system offline until it is updated. That is the safe default for anything internet-facing. Sansec, looking at the exploit code available on 22 October, judges that most online stores do not need to go offline. Which one you follow is a risk decision for you to make. What matters is that someone makes it deliberately rather than by default.

If a system has to stay up, both PHP advisories are explicit that these workarounds reduce exposure but do not make an installation safe. Use them to buy days, not weeks, and restart every worker after any configuration change:

  • Block multipart/form-data requests at the web server or proxy if the application does not need file uploads. Every known trigger uses multipart. The cost is that uploads break, so test any upload, cart or checkout flow, and remove the block after patching.
  • Set session.upload_progress.enabled = 0. This blocks the demonstrated session path of the second bug. PHP suggests keeping it off even after patching if you do not use the feature.
  • On PHP 8.5, set fatal_error_backtraces = 0.
  • Keep post_max_size conservative, cap request body size at the proxy, and lower max_input_nesting_level and the limits on input variables, multipart parts and uploads.
  • PHP-FPM: consider pm.max_requests = 1 so each worker handles one request and stale state cannot carry into the next. It costs throughput, so measure it.
  • memory_limit = -1, enforced so applications cannot override it, removes the out-of-memory trigger for the first bug. It also removes PHP's guard against a runaway script, so one request can exhaust the server. Watch memory closely and restore the limit after patching.
  • Do not use RLIMIT_AS or RLIMIT_DATA as a memory cap. The PHP advisory warns they trigger the vulnerable path.

A web application firewall helps at the edge, but only for traffic that passes through it. Cloudflare has deployed managed rules, available on its free plan too, and calls them a stopgap. Google gives equivalent Cloud Armor guidance. Neither protects an origin that can be reached directly.

Step 4 — Check whether it already happened

  • Before you rebuild a server you suspect, preserve its logs and, if you can, a disk image. Patching and redeploying destroy the evidence you would need later.
  • From 17 October onwards, look for multipart requests with unusual structure: huge or missing content lengths, very many parts or headers per part, empty file fields. Look also for bursts of out-of-memory fatal errors in the PHP log, and for worker crashes or segmentation faults.
  • On the host, look for PHP worker processes starting shells or downloading tools (CISA calls this out specifically), outbound connections from web workers, and new files in web-writable directories.
  • Your scanner and EDR vendors are shipping detections: Tenable, Google Security Operations, Wiz and others have published theirs. Make sure they are switched on, then treat a clean scan as one input, not proof.

What we do not know yet

  • Whether CISA will add either CVE to its Known Exploited Vulnerabilities catalog. That would set federal deadlines and usually follows confirmed exploitation.
  • Whether a reliable exploit against a default configuration appears. Sansec's revised view could change in either direction.
  • Which appliances and hosted products embed a vulnerable PHP. Vendor advisories are still arriving.

If you take one thing from this: the hard part is not the patch. It is knowing every place PHP runs, and which of those places has an owner. If that list takes you more than an afternoon to produce, fix that too, because the next runtime-level bug will ask the same question.

Also worth reading

Start with one piece of work.

Give us one piece of work and read access to one system. We map it and come back with what we found, what we would build and what it would take — before any commitment. You decide using our output, not our pitch.

Talk to us