← All writing
PHP

PHP2Shell, explained

A critical remote-code-execution flaw in PHP, a language behind roughly seven in ten websites. What it is, why details leaked a day early, and what to do about it now.

On 21 October 2026, PHP shipped fixes for a pair of serious vulnerabilities researchers nicknamed PHP2Shell. Because PHP runs behind roughly seven in ten websites, this is the biggest of October’s security events by sheer reach. This post explains it without the jargon, and ends with exactly what to do.

What happened

Researchers at Wiz found the first bug on 19 August and reported it to the PHP team on 24 August. PHP began a coordinated fix on 21 September, with patches and public disclosure scheduled for 21 October at 14:00 UTC. Then, on 20 October, details leaked a day early. PHP pre-announced the release rather than let the leak run ahead of the fix.

THE PHP2SHELL TIMELINEAug 19Wiz finds thefirst bugAug 24Reported tothe PHP teamSep 21PHP starts acoordinated fixOct 20Details leak; PHPpre-announcesOct 21Patches + disclosure14:00 UTCfour weeks of quiet, coordinated work
Figure 1. Four weeks of quiet, coordinated work, cut short by a leak.

The flaws allow remote code execution: an attacker who can send requests to a vulnerable PHP application may be able to run their own commands on the server. PHP rates the issue 9.2 out of 10. Early reports on the leak claimed a perfect 10; the official score is the one to trust.

How the bug works, in plain words

PHP workers handle one request after another without restarting. Some memory lives across requests. The bug is a classic lifetime mistake: a piece of memory is freed after a fatal error, but a pointer to it is left behind. The next request then uses that stale pointer. If an attacker can arrange what gets written into that freed space, they can steer what PHP does next.

ONE PHP WORKER, TWO REQUESTSrequestsPHP worker (lives across requests)global stateoutsidereader1A request runsPHP allocates its data2A fatal error hitsfreed, pointer stays3The next requestuses the stale pointer
Figure 2. One worker, two requests. The first frees data but leaves a pointer; the second trusts it.

Two things to hold onto. First, this is about the engine itself, so it does not matter how careful your own application code is. Second, the exact exploit conditions differ between the two CVEs and between sources; we are describing the general class and leaving the weaponisable details out on purpose.

“70% of websites are affected”: what that really means

About 70% of websites run PHP, and the affected range reaches every release back to 5.4. So the exposure is enormous. But “runs PHP” is not the same as “is exploitable today”: it depends on version, configuration and how the app is reachable. The sensible reading is: assume you are affected, patch, and verify, instead of arguing about whether you are one of the few who are not.

What could happen to your code and servers

  • Full takeover of the web user. Whatever your PHP process can read (config files, database credentials, uploaded files) an attacker can read.
  • A foothold for more. A shell on a web host is a stepping stone to databases, internal services and other sites on the same machine.
  • Quiet persistence. Backdoor files in upload directories are a common follow-up and survive a later patch.

What to do, in order

  1. Find every PHP. Web servers, containers, CMS hosts, old staging boxes, shared hosting. Run php -v everywhere, and check inside container images too.
  2. Update to the patched release of your line: PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35, from your distribution or from php.net. If you are on 8.1 or older there is no regular release; read our follow-up on the unpatched majority for your options.
  3. Restart PHP-FPM or Apache. A patched binary on disk does not help a worker that is still running the old one.
  4. Look for signs of trouble. Unexpected .php files in upload or cache folders, recent changes to files that should not change, odd outbound connections from the web host.
  5. Rotate secrets if you find anything. Database passwords, API keys and session secrets the PHP user could read.
  6. Reduce the damage next time. Disable dangerous functions you do not use, make upload folders non-executable, run PHP as a low-privilege user, and keep it behind a firewall that limits outbound traffic.

Sources

Wiz’s own write-up of the research is the primary source: wiz.io/blog/php2shell-php-rce. Check php.net for the fixed version numbers for your branch.

PHPSecurity
Working through something similar?
I'm Udara. I build these tools and I like talking about how they get built. Tell me what you're stuck on, or let's work on it together.
Write to me
Keep reading