DEV Community

Cover image for PHP2Shell, Explained: What the Critical PHP Vulnerability Means for Your Servers
Adnan Shakir
Adnan Shakir

Posted on Edited on Originally published at Medium AI-assisted

PHP2Shell, Explained: What the Critical PHP Vulnerability Means for Your Servers

If you run anything on PHP, the last couple of weeks have been noisy. On 21 October the PHP project shipped emergency fixes for two critical bugs, nicknamed PHP2Shell, and the reaction has swung between "this is Log4Shell for the web" and "relax, the public exploits don't even work." Both camps have a point.

I'm Adnan Shakir, Head of Technical Development at Grafdom, a web agency in Dubai. This is my attempt to separate what's confirmed from what's hype, explain how the bugs actually work, and give you something practical to run on your own servers. Everything below is accurate as of 4 November 2026, and the sources are linked at the end.

TL;DR

  • PHP2Shell is two flaws in PHP itself, CVE-2026-109618 and CVE-2026-109619. Both are rated 9.2 (CVSS v4.0) and can allow unauthenticated remote code execution (RCE).
  • The fixed versions are PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35, released on 21 October 2026. PHP 8.1 and older get no official release, though the PHP team published minimal source backports for 7.4, 8.0 and 8.1.
  • It's a runtime problem. Updating WordPress, a plugin or a theme won't fix it. WordPress.org said no WordPress update is required or planned.
  • Exploitation is real: CISA added both CVEs to its Known Exploited Vulnerabilities (KEV) catalogue on 26 October. But turning the bugs into reliable attacks on a random public site is hard, and a lot of the proof-of-concept code floating around doesn't work.
  • Only patching fixes it. Config flags and WAF rules are stopgaps.
  • In the UAE, Censys flagged 4,691 internet-facing hosts as potentially exposed on 25 October.

The timeline, short version

  • 17 October: Amazon's honeypots log the first exploitation attempt, four days before disclosure.
  • 20 October: The CVE IDs leak online, with a wrong release date and an inflated severity score. PHP announces an emergency release.
  • 21 October: Cloudflare reports early attacks (07:43 UTC). PHP ships 8.5.12, 8.4.27, 8.3.36 and 8.2.35. Researchers from Calif, Wiz and OpenAI disclose.
  • 24 October: Perplexity's Adel Karimi reports the first confirmed code execution against honeypot servers.
  • 26 October: CISA adds both CVEs to the KEV catalogue. Five days earlier it had said it hadn't seen exploitation.
  • 27 October: TU Delft's threat intelligence lab reports 50,000+ exploitation requests from 600+ IP addresses in 70 countries.
  • 29 October onward: Palo Alto Networks warns of active exploitation against internet-exposed PAN-OS management interfaces. Singapore's CSA issues an advisory on 3 November.

The two bugs, in plain technical English

This is a simplified version of the root-cause analysis in Datadog's write-up, which is worth reading in full.

CVE-2026-109618: out-of-memory corruption. PHP parses the incoming request before any of your code runs. While it builds the $_POST array, it bumps the hash table's element counters before it allocates the new key. If that allocation pushes past memory_limit, PHP throws a fatal error and leaves behind a bucket that's counted but never initialised. At request shutdown PHP destroys the array and trusts that bucket. With the right leftover heap bytes, an attacker can turn it into a fake array with a destructor callback pointed at something like system().

The catch for attackers: they have to size a field name so the memory limit is blown at exactly the right moment, groom the heap, and defeat ASLR. Wiz described a memory-disclosure trick using the PHPSESSID cookie to leak addresses.

CVE-2026-109619: stale state across requests. Some worker-wide fields point at memory that belongs to a single request. If that memory is freed without clearing the pointer (because a fatal error interrupted the reset, or a late diagnostic recreated state after cleanup), the next request handled by the same worker can follow a stale pointer. That's a use-after-free. Researchers confirmed two paths:

  • Fatal-error backtraces (PHP 8.5 only), confirmed on mod_php.
  • Upload processing, confirmed on mod_php and PHP-FPM. On FPM the application also has to perform a suitable operation after startup.

Session upload progress is enabled by default and runs even if your app never calls session_start(), which is why session.upload_progress.enabled keeps showing up in mitigation advice. This bug also needs the attacker's requests to land on the same worker, so a bigger worker pool lowers the odds per attempt without removing the flaw.

Why it's nasty. The vulnerable code runs before your application does. Authentication, nonces and custom hardening never get a chance. A tightly locked-down custom app is exactly as exposed as a default WordPress install running the same PHP.

It probably isn't the last one. The authors describe the root cause as a pattern: a memory error interrupts an operation, then cleanup trusts half-built state. They expect more instances, including possible unpatched variants on older branches.

AI found it. Researchers at Wiz, Calif and OpenAI used AI tools in the discovery. Wiz's take is that the flaws had sat in the code for years, and frontier AI models lowered the barrier to proving they were exploitable. Whether that's a one-off or the new normal, patch windows are getting shorter: remember that Amazon logged the first attempt four days before disclosure.

Who's actually exposed

  • Any PHP runtime that serves web requests. PHP's advisory names PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed. mod_php is rated highest risk because an unauthenticated request can trigger the bug before application code runs. Containers and apps that bundle their own interpreter count too, and php -v on the command line can differ from what your web server actually runs.
  • Affected releases go back to PHP 5.4. The fixes are in 8.2.35, 8.3.36, 8.4.27 and 8.5.12. PHP 8.1 and older get no official release. The PHP team published minimal source backports for 7.4, 8.0 and 8.1, and many vendors ship their own backports, sometimes without changing the version number.
  • Appliances and bundled PHP. If a vendor product embeds PHP, you may not be able to patch it yourself. The Dutch NCSC's operational inventory tracked 757 products as of 28 October: 144 fixed, 218 vulnerable, 354 still under investigation. Singapore's CSA lists PAN-OS, some Cisco, Citrix NetScaler, F5 BIG-IP and Siemens RUGGEDCOM products among the affected.
  • WordPress, Drupal, Joomla, Magento, Laravel. They all run on PHP, so they're all exposed if the runtime underneath is vulnerable. WordPress.org was explicit: no WordPress update is required or planned, the fix is the PHP update. Big hosts moved fast (GoDaddy patched managed WordPress on 21 October and standard web hosting on 22 October), but GoDaddy also warned that your PHP version number may not change after the fix. Ask your host for confirmation rather than eyeballing the number.

Is it actually being exploited? Yes, but not like the headlines say

What's confirmed

  • Attempts began before the fix. Amazon's honeypots logged the first one on 17 October, and Cloudflare reported early attacks on 21 October, hours before release.
  • Working exploitation exists. Perplexity's Adel Karimi reported code execution against honeypots on 24 October. His findings were consistent with CVE-2026-109618, with no evidence the second bug was involved. CISA then added both CVEs to KEV on 26 October.
  • The volume is high. TU Delft's team counted 50,000+ exploitation requests from 600+ IPs across 70 countries.
  • Real products are being hit. Palo Alto Networks warned of active exploitation against internet-exposed PAN-OS management interfaces. Dream Research reported a campaign that chained PHP2Shell with a Linux kernel privilege-escalation flaw (CVE-2026-46300) to root 25 servers in the US, Japan, Taiwan and South Korea. Note the chain: PHP2Shell was the door, the kernel bug was the second step.

What's shakier

  • Unit 42 walked back a headline. On 23 October it reported an AI-agent-assisted intrusion at a European government agency. On 25 October it retracted that, saying it couldn't confirm initial access was tied to PHP2Shell.
  • "AI-powered attacks" is unproven so far. Dream found AI tooling in the attacker's infrastructure but says it has no direct evidence that AI wrote the exploit.
  • Botnet attempts. As of 23 October, Sophos had seen attempts to install a Mirai-derived botnet through PHP2Shell, all unsuccessful.

The reality check

  • Sansec said on 22 October that mass exploitation looked less likely than feared, because attacks need specific knowledge of the target server and the public exploits didn't work against a default PHP install.
  • Intigriti reported on 2 November that across 24 bug bounty programs it received 37 PHP2Shell reports, accepted 3, and none of the accepted ones included a working proof of concept showing RCE or access to sensitive data. It also noted that many public GitHub PoCs were AI-generated or fake. (Intigriti sells recon tooling, so weigh the framing, but the counts are theirs.)

My bottom line is patch, don't panic. "Hard to exploit reliably" is not the same as "safe", and a KEV listing means someone is doing it.

The UAE picture

Censys counted 4,691 internet-facing hosts in the UAE as potentially exposed as of 25 October, which is 79.5% of the country's hosts where a PHP version could be identified (Khaleej Times). Treat that as a ceiling, not a body count. Censys infers exposure from detected version numbers, so a host patched through a vendor backport (version unchanged) can look vulnerable, and a host that hides its version doesn't appear in the count at all. Globally, Censys data showed around 32.5 million services still on vulnerable versions about a week after disclosure, with the same caveats.

Local hosting providers and firms were patching and advising customers to check their runtimes, and Tenable put PHP2Shell in its highest "Vulnerability of Concern" tier.

How to check your own stack

Here's the quick audit I'd run on any PHP server. Adjust package names for your distro.

# Which PHP is the web server really running? (the CLI can differ)
php -v
php-fpm -v                      # PHP-FPM; binary name varies, e.g. php-fpm8.3
apachectl -M | grep -i php      # is mod_php loaded? (apache2ctl on Debian/Ubuntu)

# Vendor backports: the version number alone may not tell you
apt changelog <php-package> | grep -E "CVE-2026-10961[89]"        # Debian/Ubuntu
rpm -q --changelog <php-package> | grep -E "CVE-2026-10961[89]"   # RHEL family
Enter fullscreen mode Exit fullscreen mode

If your distro's changelog doesn't list the CVE IDs, check the vendor's security advisory instead of guessing from the version string.

  • Restart or replace every worker still running old code. Installing the package isn't enough if PHP-FPM or Apache is still running the old binary in memory.
  • Containers: rebuild images from a patched base and redeploy. Don't just restart the old container.
  • Bundled interpreters and dev stacks (XAMPP, Laravel Herd and similar), plus vendor appliances: check each vendor's advisory.
  • Hunt for forgotten servers: old staging sites, abandoned subdomains, test containers someone spun up "just for a week" two years ago.
  • Still on PHP 8.1 or older? Get a vendor-backported build (CloudLinux, for example, published patched builds for older branches) or put the upgrade on the calendar.

What helps and what doesn't while you wait for a patch

PHP's own team says no mitigation fully blocks these bugs. Treat the list below as stopgaps, and mind the trade-offs.

  • session.upload_progress.enabled=0 mitigates the upload path of CVE-2026-109619. PHP's team suggests keeping it off after patching unless your app needs the feature.
  • fatal_error_backtraces=0 (PHP 8.5 only) blocks the backtrace path of CVE-2026-109619. It has to be loaded before request parsing, and workers need a restart.
  • memory_limit=-1 blocks the known path for CVE-2026-109618 but doesn't remove the risk of allocation failures, and it lets a runaway script eat your RAM. If you go this route, pair it with request-size limits at the proxy and memory limits at the container level.
  • Don't use RLIMIT_AS or RLIMIT_DATA. They can trigger the very allocation failures the bug depends on.
  • A WAF or reverse proxy can block requests before they reach the vulnerable parser, but verify it sees the full body, every field and chunked data. Cloudflare shipped rules before disclosure. Partial protection, not a fix.
  • Hiding errors does nothing. The stale state is still there.

How to spot trouble in your logs

No single signal is conclusive, so correlate requests, logs and processes (this follows Datadog's detection guidance).

  • Requests: multipart POSTs with PHPSESSID or PHP_SESSION_UPLOAD_PROGRESS fields on routes that don't normally use them; unusually many parts per request or deep bracket nesting (machine-generated names like files[R00001][a][a][a]); urlencoded bodies with a single multi-megabyte field name; uploads that declare a large Content-Length and then stall; a Set-Cookie: PHPSESSID= with an unusually long, percent-encoded or binary value.
  • Error logs: "Allowed memory size ... exhausted" with Unknown on line 0 (the failure hit during request initialisation, before any script ran), Apache AH00052 ... Segmentation fault (11), or a short burst of two to four memory-exhaustion errors on one worker followed by silence.
  • Processes (the strongest evidence): a web worker such as apache2 running as www-data spawning sh, bash, download tools or recon commands, followed by outbound connections. Baseline what your web user normally executes so deviations stand out.
  • Don't rely on status codes or crashes alone. A successful exploit can return HTTP 200 and leave the worker running.
# Starting points (adjust log paths for your setup)
grep -E "Allowed memory size .* exhausted.*Unknown on line 0" /var/log/apache2/error.log
grep -E "AH00052.*Segmentation fault" /var/log/apache2/error.log
Enter fullscreen mode Exit fullscreen mode

Patching closes the hole. It doesn't remove anything an attacker already planted, so if your server was exposed between 17 October and your patch date, review that window.

Beyond patching: what I'd change

  • Keep an inventory. You can't patch what you can't find. List every PHP runtime (web, containers, bundled, staging) with its owner, version and update path.
  • Mind the end-of-life dates. Per Patchstack, PHP 8.2 gets security fixes only until 31 December 2026 and PHP 8.3 until 31 December 2027, so aim for 8.4 or 8.5.
  • Plan for shorter windows. The first attempt came four days before disclosure. A monthly patch cycle doesn't cover that.
  • Limit the blast radius. None of this replaces the patch, but run PHP as an unprivileged user, restrict what the web user can execute, restrict outbound connections from web servers, and alert when a web worker spawns a shell.
  • Rotate secrets if you can't rule out exposure. One of the flaws can also leak process memory, which may hold credentials and API keys. If you can't be sure, rotate database passwords, API keys and session secrets.

What we did at Grafdom

Since the fix landed, we've updated and checked over a dozen client websites across Dubai and Abu Dhabi.

If your own servers need the same check, our team can help: grafdom.com.

FAQ

What is PHP2Shell? The nickname for two critical PHP flaws, CVE-2026-109618 and CVE-2026-109619, that can allow unauthenticated remote code execution. PHP released fixes on 21 October 2026.

Is WordPress affected by PHP2Shell? Indirectly, yes. WordPress runs on PHP, so a WordPress site on a vulnerable PHP runtime is exposed. The flaw isn't in WordPress itself, and no WordPress update is planned. The fix is the server's PHP update.

Does updating WordPress, plugins or themes fix it? No. The vulnerable code runs inside PHP, below the application layer.

Which PHP versions fix it? PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35, or a vendor-backported build that includes the fix.

Are PHP 7.4 and 8.1 affected? Yes. Affected releases go back to PHP 5.4. There's no official release for 8.1 and older, but PHP published minimal source backports for 7.4, 8.0 and 8.1, and some vendors ship their own.

Does a WordPress security plugin protect me? Not against this. The bug triggers while PHP is parsing the request, before plugin code runs. A WAF in front of the server can block known attack patterns, but PHP's team says no mitigation fully blocks these bugs.

Is PHP2Shell being exploited in the wild? Yes. CISA lists both CVEs as known exploited, and researchers have confirmed code execution on honeypots and attacks on exposed PAN-OS management interfaces. Reliable exploitation of arbitrary sites is much harder than the headline numbers suggest.

Is my UAE website at risk? If it runs PHP, the real question is whether the runtime underneath has been patched. Censys flagged 4,691 UAE hosts as potentially exposed on 25 October, though that number can include hosts patched through backports.

Should I take my site offline? The US NSA urged organisations to take affected sites offline if they couldn't fix the flaws immediately. Sansec's view on 22 October was that a typical store doesn't need to go offline, but should update anyway. My take: if you can patch today, patch. If you can't (end-of-life PHP, a vendor appliance), restrict exposure behind a WAF or VPN, or take it down until you can.

How do I know if I was compromised? Check your logs back to 17 October, when the first attempts were recorded. Look for unfamiliar admin accounts, new files you didn't add, and web processes spawning shells. Patching doesn't remove anything planted earlier.

What about Python sites? PHP2Shell only affects PHP. Python apps aren't affected by it. A separate, unrelated supply-chain attack hit the LiteLLM Python package on 21 October (version 1.107.0 on PyPI, live for about two hours).

About the author

Adnan Shakir is Head of Technical Development at Grafdom, an award-winning digital media agency in Dubai, UAE. Established in 2005, Grafdom designs, develops and maintains websites for enterprise organisations, multinational companies and government departments across Dubai and Abu Dhabi. With two decades of expertise, it has become a trusted technology partner & advisor to senior leadership teams throughout the Middle East. Grafdom has earned a reputation as the agency of choice for the largest real estate companies, education institutions and banking businesses in the Gulf.

Sources

Top comments (0)