Skip to content
tak.tn
← Back to blog
7 min read

PHP2Shell: patch PHP now, then assume your secrets leaked

On October 21 the PHP project shipped emergency releases for two vulnerabilities nicknamed PHP2Shell: CVE-2026-109618 (out-of-memory corruption) and CVE-2026-109619 (stale global state, a use-after-free). Both are rated CVSS v4.0 9.2, both allow an unauthenticated remote attacker to execute code as the PHP worker process.

The Drupal Security Team issued PSA-2026-10-20 the same day. Its wording is unusually blunt: “Updating to a PHP release containing the patch to these vulnerabilities is the only complete mitigation.”

Five days on, here is what actually matters — including the part most coverage has buried.

Are you affected? Almost certainly yes

This is in PHP itself, not in a framework or a module. Every installation serving web requests is in scope: PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed. PHP considers mod_php the highest risk, because there the request can be handled before any application code runs.

Branch Fixed version
PHP 8.5.x 8.5.12
PHP 8.4.x 8.4.27
PHP 8.3.x 8.3.36
PHP 8.2.x 8.2.35
PHP 7.4 – 8.1 No upstream release — but your distribution probably patched it. See below
PHP 5.4 – 7.3 End of life. No fix from the PHP project

Check what you are actually running, not what you think you are running:

php -v          # the CLI binary — often NOT the one serving your site
php-fpm -v      # the FPM binary, which usually is

On Debian, Ubuntu and RHEL, php -v will lie to you about patch status. Distributions backport the fix into the version they already ship, so the version string never changes. A patched Ubuntu 22.04 box still reports 8.1.2. Check the package version instead:

dpkg -l | grep -E "^ii\s+php[0-9.]+-(fpm|cli)"   # Debian / Ubuntu
rpm -q php-fpm                                   # RHEL / Alma / Rocky

This trap cuts both ways: people are declaring themselves vulnerable when they are fine, and fine when they are vulnerable. Trust the package manager, not the banner.

Updating Drupal or WordPress does nothing here

This is the misconception costing people time this week. There is no Drupal release that fixes this, and the PSA does not claim Drupal core is vulnerable — it places the issue squarely in the runtime and notes that “the remit of the Drupal Security Team remains limited to code hosted on Drupal.org’s systems.” The same applies to WordPress: no plugin update, no core update, no security plugin patches a hole in the PHP binary.

If your host manages PHP, this is their job and you need their timeline in writing. If you manage it, it is yours. Researchers at Wiz reportedly demonstrated the chain against current WordPress, Drupal and Joomla container images, so “we’re on a standard stack” is not reassurance.

The part being buried: patching does not undo a leak

CVE-2026-109618 can disclose server memory on its own. Sansec’s analysis describes PHP’s upload-progress handler returning freed worker memory to the client in a PHPSESSID cookie — memory that “can contain passwords, session tokens, API keys and TLS private keys from other requests”. It works “even when the application never calls session_start()”.

Read that twice. The leaked memory comes from other people’s requests on the same worker. One attacker’s request can hand them another visitor’s session token.

None of the advisories I have read tell you to rotate anything. They tell you to patch. That is correct but incomplete, and the gap is my main reason for writing this: patching closes the hole, it does not un-leak what already went out the door. If you were exposed to the internet on a vulnerable version — which, before October 21, was everyone — my own view is that you should treat the following as potentially disclosed and rotate them:

  • Session keys and hash_salt (Drupal) / AUTH_KEY and friends (WordPress) — then force re-authentication
  • Database credentials
  • API keys and tokens held in application config or environment
  • SMTP and payment-provider credentials
  • TLS private keys, if your termination happens on the same host as PHP

That is a judgement call rather than vendor guidance, and rotation has its own operational cost. Make it deliberately. But “we patched on Wednesday” is not the same as “we are clean”.

You probably cannot tell whether you were hit

I would love to give you a log signature. There isn’t a reliable public one. Sansec notes the RCE and memory-disclosure paths execute inside PHP, before WAF rules apply — so a clean WAF log proves nothing.

What is known about timing: Amazon Threat Intelligence observed an exploitation attempt against its honeypot network on October 17 — four days before public disclosure — and recommends starting any investigation from at least that date. Cloudflare reported early attacks on the morning of October 21, before the patch landed.

Sources genuinely disagree on scale. Amazon describes broad exploitation in the wild; Bitdefender reported none in its telemetry as of October 22; the PHP Foundation said it had identified no functional exploits at release; and as of October 23 neither CVE was in CISA’s KEV catalog. Treat confident claims in either direction — including “nothing happened” — with suspicion.

Upstream EOL is not the same as unpatched

This is the part most coverage has got wrong this week, and it is what saved a lot of people — including teams I work with.

PHP 8.1 reached upstream end of life on December 31, 2025, so php.net ships nothing for it. But your Linux distribution is not php.net. Canonical released fixes for every affected supported Ubuntu release on October 21, the same day as upstream, through USN-8948-1 (and USN-8948-2 for Ubuntu Pro releases). On Ubuntu 22.04 LTS, php8.1 is fixed in 8.1.2-1ubuntu2.28 — in standard updates, no Ubuntu Pro subscription required. The Launchpad changelog carries a maintainer date of October 19, two days before public disclosure: distributions were briefed in advance.

Ubuntu 22.04 LTS keeps receiving free security updates into 2027 — sources differ on whether standard support ends in April or May 2027, so check Canonical’s own lifecycle page before you plan a migration around it, and note that Ubuntu Pro/ESM extends coverage into 2032. Debian and the RHEL rebuilds did the same backport work.

Credit where it is due. This is unglamorous, invisible labour: distribution security teams taking a patch written for a branch they do not control and carefully grafting it onto a version upstream abandoned ten months ago. The Ubuntu Security team and the wider Debian and Ubuntu community maintainers are the reason a large share of the web was patched on day one despite running PHP 8.1. If you were fine this week without doing anything heroic, that is who to thank.

Who is genuinely stranded, then, is a smaller but real group: anyone on PHP 5.4 through 7.3, where nobody ships a fix; anyone who compiled PHP from source on an old branch; anyone on a distribution release that is itself out of support; and anyone whose shared host simply has not acted. That is still the Drupal 7 site nobody wanted to migrate and the WordPress install on cheap hosting. CISA’s guidance for those cases is uncomfortable and correct: if you cannot update, take the system offline until you can.

This is the argument I have been making all year in a less dramatic register — in the Drupal security playbook I listed PHP version EOL as a meta-risk, and in the Drupal 10 end-of-life post as a deadline. PHP2Shell is what that risk looks like when it arrives: not a gradual decline, but one Wednesday on which your platform becomes unpatchable.

If you truly cannot patch today

PHP published interim configuration changes. They reduce exposure and do not make an installation safe, and every PHP worker must be restarted after applying them:

; CVE-2026-109618 — set so applications cannot override it
memory_limit = -1

; CVE-2026-109619
session.upload_progress.enabled = 0
; PHP 8.5 only
fatal_error_backtraces = 0

Treat these as a bridge measured in hours, not a configuration you keep.

The short version

Patch to 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35 today — or to your distribution’s patched package, and verify it with dpkg/rpm rather than php -v. Get your host’s timeline in writing if they own the runtime. Rotate your secrets rather than assuming you were lucky. And if you got through this one only because Canonical was still backporting for you, treat that as the warning it is: that safety net has an expiry date too.

Stuck on an EOL PHP version with a site nobody dares touch? That is exactly the migration work I do — and the audit that tells you how exposed you are comes first.

A Drupal project or a technical SEO challenge?

Let's talk. Reply within one business day, no strings attached.

Get in touch