Skip to main content

PHP2Shell: patch it calmly and ignore the exploit sellers on X

· 10 min read
Victor Jimenez
Senior Product Engineer

PHP2Shell is the name for two use-after-free flaws in the PHP engine, and PHP shipped the fixes on October 21, 2026. My position: patch on your normal urgent schedule, check the exploit conditions against your own servers, and do not download or run anything a stranger on X calls an exploit or a fix. The bugs deserve a patch, the panic deserved much less, and the exploit and fix scripts shared on social media were worse than useless.

I work on PHP and CMS sites, including Drupal and WordPress, so this is the kind of advisory I read and triage. I did not run any exploit and I measured nothing. Everything below is the published research, my reading of it, and what I would do with it.

The bugs and the fixed versions​

Both flaws are in the PHP engine. They are not in Drupal core, WordPress core or a plugin, so the fix is a newer PHP on the server, and a CMS update does not replace it. The fixed releases are 8.5.12, 8.4.27, 8.3.36 and 8.2.35 (Datadog, JFrog, Sansec).

PHP 8.1 and older are end of life and need a package from your distributor or vendor. If a server runs one of those versions, the urgent work is finding that package. A new PHP release does not cover it.

A use-after-free bug means the engine keeps using a piece of memory after it has released it. Each CVE is rated 9.2 on CVSS v4.0, the standard 0 to 10 severity scale. The same vendor scoring sets high attack complexity, because exploitation depends on the allocator layout, the build and worker scheduling (watchTowr, Datadog).

The exploit conditions in plain words​

The trigger is a fatal error during a request, typically out of memory when the request crosses memory_limit (Sansec). JFrog lists the configuration requirement as "session.upload_progress.enabled=On (factory default) and multipart uploads accepted." Multipart uploads are the form encoding browsers use to send files, and upload progress is the PHP feature that tracks those uploads in the session.

The chain needs an earlier error that skips cleanup, then two multipart uploads handled by the same worker (JFrog).

Apache with mod_php is the confirmed remote code execution target. PHP-FPM, the process manager that runs a pool of PHP workers, is "susceptible through state published after successful startup", in JFrog's words. JFrog calls FPM susceptible, not confirmed, so I treat FPM as exposed but one step behind.

The same-worker step is where server setup changes the odds. JFrog says setting pm.max_requests=1, which makes each FPM worker exit after one request, breaks the same-worker requirement.

For one of the two CVEs, Datadog says a larger worker pool lowers the success rate of each attempt but does not remove the flaw. So a large pool is not a reason to move the server out of the urgent cycle.

The hype against the conditions​

Sansec's assessment is direct: "An attack needs specific knowledge of the target server and specific conditions on it." Sansec says this makes mass exploitation less likely than first expected, and adds: "The public exploits do not work against a default PHP installation." Most of those exploits need the target application to already have a local file inclusion bug, a flaw that lets an attacker make the application load a file of their choice, which is a severe problem on its own.

Some proofs of concept only work because the tester added such a bug to the test server first (Sansec). A demo that needs a planted severe vulnerability before it works mainly proves that the planted vulnerability is severe. Sansec also notes that the Log4Shell and Shellshock attack waves used one request that worked against any vulnerable server, and nobody has shown such a request for PHP2Shell.

A widely shared Wiz headline said "AI uncovers critical RCE vulnerabilities affecting 70% of the Internet" (Wiz). I read that 70% as the reach of PHP. The share of exploitable sites depends on the conditions above, and none of the sources here gives that share.

The exploitation picture is disputed, which is why I still treat the patch as urgent. watchTowr reports exploitation in the wild (watchTowr).

Amazon honeypots logged an attempt on October 17, four days before disclosure, and Amazon says it cannot tell whether those attempts would have worked on real systems (SecurityWeek). As of October 22, 2026, CISA had not added either CVE to its Known Exploited Vulnerabilities catalog (The Hacker News).

Fake exploits and fake fixes​

JFrog says "some users were taking advantage of the opportunity to spread fake PoCs as pranks." In one repository a Base64 string looked like malware, but "the script appears to change the victim's wallpaper to NSFW content." A GitHub issue on another repository calls it a fictional narrative wrapped around two real CVE IDs (ASEC, JFrog).

The PHP project reportedly said it had no evidence of working exploits, only these:

"incomplete, misguided, and non-working generated ones"

The PHP project, as reported in the ASEC and JFrog analyses

watchTowr reportedly said the shared exploits either do not work, only test timing differences, or crash the target (ASEC, JFrog). That is three ways to fail, and none of them is remote code execution.

The fix side was worse. ASEC warns that some scripts shared as mitigations after disclosure run with root privileges, which means full control of the server, and can become an attack path disguised as a security tool. One of them states that AI produced it and that it comes with no guarantees, the most accurate sentence in the script (ASEC).

My call: a stranger's script that runs as root on a production server is a bigger risk to most PHP sites than PHP2Shell on a default installation. The bug needs specific conditions. The script needs one person to paste it.

Run nothing from the feed

Do not download or run code that a stranger on social media calls a PHP2Shell exploit, scanner or fix. Take the patched PHP from the PHP project, your distributor or your vendor.

Urgency by server setup​

Sansec says to update PHP on every server, and I agree. The table is my order inside the urgent cycle, based on the published conditions. No row is a reason to skip a server.

Server setupWhat the sources sayMy order
Apache with mod_php, multipart uploads accepted, upload progress onConfirmed remote code execution target (JFrog)First
Application with a known local file inclusion bugMost public exploits need that bug (Sansec)First, and fix that bug as well
PHP 8.1 or olderEnd of life, needs a distributor or vendor packageFirst for planning: find the package
PHP-FPM, multipart uploads accepted, upload progress onSusceptible (JFrog); a larger pool lowers each attempt's success but keeps the flaw (Datadog)Same cycle, right after the first group
PHP-FPM with pm.max_requests=1, or multipart rejected at the web serverOne step of the JFrog chain is brokenNormal urgent schedule, still patched

Sansec also says there is no need to take a store offline. The bug is serious enough to patch this cycle and narrow enough that an emergency shutdown is out of proportion.

Interim mitigations and what they cost​

Every mitigation below is partial, and each one has a cost or a gap. Use them only on a server you cannot update yet.

  • Reject multipart/form-data at the web server. This breaks uploads, so test checkout afterwards.
  • Set session.upload_progress.enabled to off. Datadog says this setting alone does not fully protect.
  • Set memory_limit to -1 to remove the typical out-of-memory trigger. Sansec warns that one request can then use all server memory.
  • Set pm.max_requests=1 on PHP-FPM, which JFrog says breaks the same-worker requirement. It does nothing for Apache with mod_php, which is the confirmed target.
  • Add a web application firewall rule if you like, but Sansec says it is not a fix.

Removing the memory limit takes away one trigger and leaves the flaw in the binary. It also gives you a server that one request can fill. I would use it last.

Patching is the only full fix

The settings above reduce exposure on a server you cannot update yet. Update PHP as soon as the package is available for that server.

The third CVE disclosed two days later

Two days later, PHP disclosed a third CVE and called it unlikely in practice. It needs an application that sets session.serialize_handler to php_binary or php_serialize and then switches it to php with ini_set() before session_start(), with upload progress enabled (The Hacker News). I would search the codebase for ini_set calls on that setting before spending more time on it.

Verify the PHP that serves your requests​

The PHP that matters is the one answering web requests, which can differ from the one on the command line. These checks confirm both the version and the conditions:

  1. Put a phpinfo() page behind authentication, load it through the site, and read the PHP version, the Server API line (Apache handler or FPM), session.upload_progress.enabled and memory_limit. Delete the page afterwards.
info.php
<?php
phpinfo();
  1. On the server, run the FPM binary that the pool uses with -v (for example php-fpm -v; the name varies by distribution), not the first php on the path.
  2. Check whether the web server passes multipart/form-data requests to PHP at all. An application without an upload form does not prove that the web server rejects multipart requests, so check the web server configuration, which is where the sources place the rejection rule.

The limitation of my table: it rests on the published conditions. If a source shows one request that works against a default installation, or CISA adds either CVE to its catalog, I would drop the ordering and patch everything at once.

References​