Skip to content

PHP2Shell Explained: Who Is Affected and How to Patch

Two critical PHP core bugs give attackers code execution before your app runs. What they are, which versions are exposed, how many sites sit on branches with no fix, and the exact steps to patch a Laravel server.

Hoceine El Idrissi8 min read
PHP2Shell Explained: Who Is Affected and How to Patch

PHP2Shell Explained: CVE-2026-109618 and CVE-2026-109619

On October 21, 2026, the PHP project shipped an emergency release: 8.5.12, 8.4.27, 8.3.36 and 8.2.35. It fixes two bugs in the PHP interpreter itself, nicknamed PHP2Shell, each rated 9.2 on CVSS v4.0. Both let an attacker run code on the server without logging in, and on a default configuration.

This is not a WordPress plugin bug or a Laravel bug. It sits in the runtime, so every PHP application that serves web requests is in scope: PHP-FPM, Apache mod_php, php-cgi, LiteSpeed and FrankenPHP.

If you only read one line: run php -v on every server and container, then upgrade to one of the four versions above and restart every PHP worker.

What the two bugs are

Both bugs come from the same old idea, first published by Stefan Esser back in 2004: if PHP is interrupted in the middle of building internal structures, cleanup code later trusts data that was never finished.

  • CVE-2026-109618. PHP runs out of memory partway through setting up a request. The fatal error jumps out with longjmp() and leaves request memory half initialised. Researchers describe it as a use-after-free in the session upload progress unserializer, a feature (session.upload_progress) that is enabled by default.
  • CVE-2026-109619. A fatal error during backtrace handling leaves global state pointing at memory that has already been freed. The next request handled by the same worker reads that leftover data, which an attacker can shape into code execution.

The second one is nasty for long running setups. A pool of PHP-FPM workers, or an Octane or FrankenPHP worker that lives for thousands of requests, keeps the poisoned state around.

On Apache with mod_php, the attack can complete before your application code runs at all. No route, no middleware and no framework sees the request.

PHP2Shell timeline from first probes to patch

Who found it, and which AI models helped

Two teams found the bugs independently, both with AI models doing a large part of the work. PHP's official advisory credits four reporters (lcfr-hax, sagitzadik-wiz, tomash-areion and amyb-oai), and PHP core developers wrote the fixes.

  • Calif. Researcher Ryan Austin worked on PHP as part of OpenAI's "Patch the Planet" project, using OpenAI's GPT-5.6 Sol model. Sansec's timeline says Calif reported the first bug to PHP on August 11, 2026.
  • Wiz Research. Wiz says it used Gemini 4 Argon, GPT-5.6 Sol and its own tool Wiz Atlas, and that "Gemini 4 Argon made an invaluable contribution to finding the vulnerability." Wiz found its first bug on August 19, confirmed unauthenticated RCE against Drupal on August 20 and WordPress on August 21, and reported to PHP on August 24. Wiz also named the bugs PHP2Shell.
  • OpenAI is credited in the advisory and by Wiz for help with discovery, coordination and patch verification.

PHP acknowledged the reports on September 21 and shipped the fix on October 21: about ten weeks from the first report.

The timeline, and why it was messy

  • October 17. Amazon saw exploitation attempts, four days before the embargo was due to lift.
  • October 20. Details leaked on social media. PHP moved the release forward to October 21 at 14:00 UTC. watchTowr publicly confirmed the bugs were real.
  • October 21. Fixed releases shipped. CISA published an alert urging immediate patching. watchTowr said its honeypots were already seeing exploitation; CISA said it had not observed any yet.
  • October 23. PHP disclosed a third RCE, CVE-2026-115560. It only affects applications configured in an unusual way and PHP rates it unlikely to matter.
  • October 25. Unit 42 retracted an update that tied an intrusion at a European government agency to PHP2Shell, saying it could not confirm the initial access.

That early picture is now settled: PHP2Shell is actively exploited. Amazon says it is being broadly exploited in the wild, and SecurityWeek reports attacks have moved from probes to working shells. Amazon still cannot explain how an attacker had a working exploit on October 17, so start any investigation from that date, not from the disclosure. Be careful with "weaponised" proof of concept bundles circulating online; many are untrustworthy.

Palo Alto's Cortex Xpanse counted more than 22.6 million internet facing PHP instances potentially exposed. Bugs reach back to PHP 5.4.0, released in 2012.

The real problem: half the PHP web has no official fix

PHP only supports the 8.2 to 8.5 branches. Everything older is end of life, so there is no upstream patched release for it. W3Techs says PHP runs 70.3% of websites with a known server language. Here is how those sites split by version:

Share of PHP websites by version, and which have an upstream fix

Add up the red bars and roughly 52% of PHP websites run a branch with no official PHP2Shell release: 8.1 and 8.0, all of PHP 7 and all of PHP 5. Some of them will get vendor backports from Debian, Ubuntu, Red Hat or cPanel's CloudLinux. Many will not.

That number, not the bug itself, is the story of this week. The vulnerable code is old; what makes it dangerous is how many servers never moved off old PHP.

How to check if you are exposed

The CLI and the web server can run different PHP binaries. Check both.

bash
php -v
php-fpm8.3 -v
ls /etc/php/

Then confirm what the web process actually runs. A throwaway route works, delete it right after:

php
Route::get('/_v', fn () => PHP_VERSION)->middleware('auth');

Safe versions are 8.5.12+, 8.4.27+, 8.3.36+, 8.2.35+, or a distro package whose changelog names both CVEs.

Patching, by platform

Ubuntu or Debian with the Ondřej Surý PPA (most Forge servers):

bash
sudo apt update
sudo apt install --only-upgrade 'php8.3*'
sudo systemctl restart php8.3-fpm

Laravel platforms:

  • Laravel Cloud apps were patched in place.
  • Forge servers need the PHP update above. Forge does not do it for you.
  • Vapor apps need a redeploy so Lambda picks up the patched runtime.

Docker: bump the base image tag (for example php:8.3-fpm pulls 8.3.36), rebuild with --pull --no-cache, and redeploy. An old image sitting in a registry stays vulnerable forever.

Octane, FrankenPHP and queue workers: a reload is not enough. Replace the FrankenPHP binary or image and fully stop and start every long running process:

bash
php artisan octane:stop && php artisan octane:start
php artisan queue:restart

Shared hosting: many hosts (SiteGround, for example) applied protections for every customer. Open your control panel, pick a patched version, and ask support for a written answer if you are on 7.x.

If you cannot patch today

PHP is clear that updating is the only complete fix. These settings only close some attack paths and buy you hours, not weeks:

ini
session.upload_progress.enabled = 0
  • Lower post_max_size and enforce request body limits at NGINX or your load balancer.
  • Put a WAF rule in front (Cloudflare, AWS and Palo Alto all shipped signatures).
  • Setting memory_limit = -1 removes one trigger but invites denial of service. If you do it, set a container or cgroup memory limit as the real boundary.

After patching

Patching stops new attacks. It does not remove an attacker already inside. If your server was reachable on a vulnerable version between October 17 and the day you patched, look for:

  • New PHP files in public/, storage/ or upload folders, especially ones with eval, base64_decode or assert.
  • PHP worker processes spawning sh, curl or wget.
  • Unknown admin users, new SSH keys, new cron entries.

If you find anything, rebuild from a clean image and rotate every secret in .env: APP_KEY, database passwords, mail and payment API keys.

Next

I wrote two follow ups: the rest of this brutal security week (GitLab, Java, NGINX, Node and a record Patch Tuesday) and should you leave PHP, and is Laravel safer than plain PHP.

Sources