Enterprise-Grade, Explained · For engineers

PHP2Shell: the PHP bug's only confirmed victims so far are firewalls

PHP2Shell was billed as a WordPress disaster. The only verified victims so far are 24 Palo Alto firewalls and a management server, running PHP only the vendor could patch, and the fix for their builds came after the attack.

Short answer PHP, the language behind WordPress and many websites, had two serious bugs, nicknamed PHP2Shell, that let attackers take over servers without a password. The only confirmed victims so far are company firewalls quietly running old PHP. Patch PHP everywhere, ask device vendors for fixes, keep admin pages off the internet.

PHP is the programming language behind WordPress and a large share of the web's sites. PHP2Shell is the nickname for two bugs in PHP itself, CVE-2026-109618 and CVE-2026-109619, which the PHP project disclosed and fixed on 21 October. Both let someone run their own code on a server without logging in. With PHP under so many sites, the bugs were billed as a disaster for every WordPress install.

What actually happened is narrower. The only real-world break-ins confirmed so far hit firewalls, the boxes that sit between a company network and the internet, made by Palo Alto Networks, a major security vendor. Their operating system, PAN-OS, quietly runs an old PHP for its admin web page, one the owners cannot update themselves; the vendor's fix came after the attack. The PHP you patch with your web servers is not all the PHP you run.

At 18:14 UTC on 23 October, an automated script rooted one of those firewalls. Its configuration, according to a report by Dream, a cyber-defence company whose researchers recovered the attacker's files, points to a US government-affiliated organization. The firewall crashed soon after, probably under roughly 900 MB of exploit traffic, and never came back. At 10:09 UTC the next day the attacker rooted a second firewall of the same organization. Less than 90 minutes later it used that foothold to root the internal server that manages all of the organization's firewalls.Source 1

§1

Twenty-five machines rooted, and none of them was a WordPress site

Dream's researchers recovered the attacker's own workbench: a custom PHP2Shell exploit tailored to PAN-OS, chained with a Linux kernel privilege-escalation bug called Fragnesia (CVE-2026-46300), target lists and exploitation logs. The logs record 24 firewalls rooted, all but one in an automated batch, plus the internal firewall management server reached through a tunnel: 25 machines in totalSource 1. Most got only a web shell, a hidden page for running commands later; the organization Dream links to the US government also got a tunnel and an attack on its user directory.

Palo Alto's threat-research team, Unit 42, independently verified the attacker's tooling and confirmed the resultsSource 2. Palo Alto's security advisory, raised to Critical on 27 October, reports active exploitation of management interfaces exposed to the internetSource 3. Unit 42 says about 0.02% of its installed base had an internet-facing management interface and was impacted. It gives no countSource 2.

§2

Two bugs in the code every PHP request touches

Both bugs sit in memory accounting and error handling, which nearly every request passes throughSource 4. CVE-2026-109618 happens when a request hits PHP's memory limit at the wrong moment: PHP abandons the request halfway through setting it up, and the cleanup code then trusts the half-built data. CVE-2026-109619 is about leftovers: some internal state outlives the request that owns it, and the next request served by the same worker can act on memory that was already freedSource 5.

Neither needs a bug in your application. PHP lists every SAPI, the layer that plugs PHP into a web server, as at risk: PHP-FPM, Apache mod_php, php-cgi, FrankenPHP and LiteSpeed. It rates mod_php highest, because there the attack can complete before any application code runsSource 5. The CVE IDs leaked on 20 October with a wrong score of 10.0Source 4. PHP scores both bugs 9.2 out of 10 under CVSS v4.0, the standard severity scale; the US National Vulnerability Database (NVD) scores them 9.8 and 8.1 under v3.1Source 6Source 7.

The "every PHP since version 5" line from the leak thread is close but loose. Calif, a security research firm and one of those that reported the bugs, dates the earliest affected path to PHP 5.4.0Source 8. PHP itself fixed only supported branches, plus source backports for 7.4, 8.0 and 8.1Source 5.

§3

Why firewalls were the first confirmed victims

The PAN-OS 12.1 and 12.2 builds the attacker went after run PHP 8.0.30, and the 11.1 builds in its notes run PHP 7.4.33Source 1. Neither branch gets releases from the PHP project. You cannot apply a source backport to a firewall; you wait for the vendor. Palo Alto's advisory records fixed hotfixes as released branch by branch from 25 to 29 October UTC (the advisory page shows dates in your own time zone). The 12.1 and 12.2 builds the attacker targeted got their first fixes at 04:03 UTC on 27 October, almost three days after the last firewall was rootedSource 3.

Palo Alto's paid intrusion-prevention signatures, out from 21 October, protect the management interface only if its traffic is routed through a data-plane port and inspectedSource 3, which is not how the management port works by default.

Then the uniformity. PHP's own advisory says a working exploit depends on the PHP build, extensions, frontend and allocator layoutSource 9. On a fleet of web servers those vary. On appliances they don't: every unit on a given firmware build carries the same binary. Nine version profiles, one of them calibrated on a live system, covered the 12.1 and 12.2 builds on the target list. The batch tried 240 firewalls, five at a time; 24 were rooted in the end, one of them in a follow-up runSource 1. An appliance fleet is a monoculture, which makes it a more uniform target than a varied estate of web servers.

Last, exposure and ownership. The attacker found about 19,000 exposed PAN-OS management interfaces through FOFA, an internet search engineSource 1. Palo Alto says the management interface is not exposed by defaultSource 2. Web teams patch PHP, network teams patch firmware, and the firewall's PHP sat in neither queue.

§4

Four numbers that measure four different things

Four PHP2Shell counts (30 Oct) as cards: 76,021 exploit requests at TU Delft sensors, of which 55,661 were probes only; 197 successful exploits on GreyNoise's own sensors, 186 from one IP; 25 real machines rooted, per Dream.
Image description

A figure titled 'PHP2Shell: four numbers, four different things'. Live counts read 30 October 2026: TU Delft at 10:52 UTC, GreyNoise at 10:45 UTC. The counts come from different datasets and do not narrow down into each other; only the probes sit inside the total above them. Card 1, labelled Attack traffic: 76,021 exploit requests that reached TU Delft's honeypots and network telescope, from 680 IPs in 73 countries, 21 to 30 October, counted by the Delft Threat Intelligence Lab. Card 2, nested under card 1: of which 55,661 went no further than a probe, from 566 IPs, same TU Delft dataset. Card 3, labelled Traps that fired: 197 successful exploits against GreyNoise's own deliberately vulnerable sensors, from 2 attacker IPs, 186 of them from one IP in under five minutes on 29 October, on a different sensor network from TU Delft's, counted by GreyNoise. Card 4, highlighted and labelled Real victims: 25 machines rooted, 24 Palo Alto PAN-OS firewalls and 1 firewall management server, from the attacker's own logs, 23 to 24 October, reported by Dream Research and verified by Palo Alto Networks Unit 42. Footer: Requests measure effort. Sensor hits measure traps. Only the last row counts real victims, and none was a public website.

Fig. 1 — The counts come from different datasets and are not subsets of each other, except the probes inside TU Delft's total. Live pages read 30 Oct 2026: TU Delft at 10:52 UTC, GreyNoise at 10:45 UTC. Rooted machines: Dream Research, verified by Unit 42.

Coverage tends to put one of these next to the word "attacks" and let readers assume victims.

76,021 requests, 55,661 of them probes. As of 10:52 UTC on 30 October, the live counter of a threat lab at TU Delft, a Dutch university, showed 76,021 exploitation requests since 21 October from 680 source IPs in 73 countries. They hit the lab's honeypots, decoy servers built to be attacked, and its network telescope, unused addresses that record stray traffic. Of those, 55,661 requests went no further than a probeSource 10. A request is attacker effort, not a result.

197 successes, on traps. As of 10:45 UTC on 30 October, GreyNoise, a company that runs sensors across the internet, had confirmed 197 successful exploitations, from 2 attacker IPs, against its own vulnerable sensorsSource 11. Its definition is strict: a session in which the web server ran operating-system commands. The sensors are traps on a different network from TU Delft's, so the totals cannot be added. On 29 October the news site The Record reported at least six, GreyNoise's count until 19:55 UTC that daySource 12. That evening one IP scored 186 successes on GreyNoise's traps in under five minutesSource 11.

25 rooted machines. Dream's count comes from the attacker's own logs, and Unit 42 checked it. It is the only number of the four that counts real victims.

Amazon's own headline speaks of exploitation "prior to public disclosure". The evidence is one attempt on Amazon's MadPot honeypots on 17 October, and AWS says it is unclear whether its pre-release attempts would have worked on real systemsSource 13. And the government link, the Chinese attribution and the "AI-built exploit" are Dream's reading of the evidence. Dream says it has no direct evidence the AI tools wrote the exploitSource 1.

§5

How to check yours

Find every PHP runtime, including the ones you didn't install

Work through each place PHP hides:

  • Hosts: command -v php php-fpm php-cgi, then the package list (dpkg -l | grep -i php or rpm -qa | grep -i php). Check for Apache's PHP module with apachectl -M | grep -i php: mod_php is the highest-risk setup.
  • Runtimes outside the package manager: find / \( -name 'libphp*.so' -o -name 'php-fpm*' -o -name 'php-cgi*' \) 2>/dev/null finds copies that vendors bundle with their own software, on every mounted filesystem.
  • Containers: for each image you run, docker run --rm --entrypoint php <image> -v, or an image scanner that reads package metadata.
  • Appliances and vendor VMs: list every device with a web interface (firewalls, VPN gateways, NAS, storage, hypervisor and backup consoles) and search each vendor's advisories for CVE-2026-109618. You cannot run php -v on a sealed appliance, so the vendor's advisory is the answer.

Check the version, and don't trust the number alone

The fixed releases are 8.5.12, 8.4.27, 8.3.36 and 8.2.35. Distributions backport fixes without changing the upstream version, so an older number can still be patched. Check the installed package's changelog for the CVE: zcat /usr/share/doc/php8.3-fpm/changelog.Debian.gz | grep CVE-2026-109618 on Debian or Ubuntu, rpm -q --changelog php-fpm | grep CVE-2026-109618 on RHEL-family systems. Also check the binary that actually serves web traffic, such as php-fpm8.3 -v, because the CLI php can be a different build.

Apply the workaround where you cannot patch yet

For CVE-2026-109619, set session.upload_progress.enabled=0 where it applies before request parsing: php.ini, an FPM pool with php_admin_value[session.upload_progress.enabled] = 0, or Apache's php_admin_flag session.upload_progress.enabled off. Not ini_set() and not .user.ini. Then restart every worker. PHP is clear that this blocks the confirmed session paths and not other variantsSource 5. On PHP 8.5, also set fatal_error_backtraces=0Source 14.

For CVE-2026-109618, PHP's partial measure is memory_limit=-1, set so applications cannot override it. It removes the attacker-controlled failure, not every path to the bug, and adds a memory-exhaustion risk, so cap memory per worker with a cgroupSource 9. On an appliance, the workaround is the network.

Take management interfaces off the internet

Palo Alto's guidance is to allow management access only from trusted internal addresses or a single jump boxSource 3. Check from outside your network, or look your address ranges up in an internet scanning service. On PAN-OS, also check data-plane interfaces with a management profile attached, which the advisory says are affected too. Palo Alto's FAQ says GlobalProtect, its VPN service, is not affected; Dream says the same web server fronts its portalSource 3Source 1. Until Palo Alto addresses that, keep both off the open internet where you can.

If a management interface was reachable from the internet at any time since 17 October, start the investigation from that date, as AWS advisesSource 13. Patching does not remove a web shell. Dream's artifacts include a shell at /unauth/php/change_password.php and tunnel scripts under /usr/local/lib/.panops/Source 1. Palo Alto's advisory does not list indicators, so ask Palo Alto support for them and run Unit 42's hunting queriesSource 2.

Both PHP CVEs have been in CISA's Known Exploited Vulnerabilities (KEV) catalog since 26 OctoberSource 7. CISA is the US government's cyber-defence agency, and a KEV listing sets patch deadlines for federal agencies. Patch the kernel too: Fragnesia (CVE-2026-46300, in KEV since 28 October) turned the PHP foothold into rootSource 15Source 1.

§6

What we would change: inventory runtimes, not servers

Most patch processes are keyed to roles: web servers get PHP updates, firewalls get firmware. PHP2Shell's confirmed victims fell between the two lists. Keep an inventory of runtimes, including the ones inside firmware, containers and vendor images, and ask each appliance vendor in writing which language runtimes and versions it bundles.

  1. List every PHP runtime, not every web server Including container images and appliances.
  2. Confirm the fix, not the version string A fixed release, or a vendor package whose changelog names both CVEs. Restart every worker.
  3. Turn off session upload progress where you cannot patch Startup config, then restart every worker.
  4. Take management interfaces off the internet Trusted internal addresses or one jump box. Test from outside your network.
  5. If a management interface was exposed, hunt from 17 October A patch does not remove a web shell.
  6. Match the KEV feed against your inventory daily Including CVE-2026-46300, the kernel bug in the chain.

Sources

  1. Dream Research: Chained PHP2Shell exploit roots 25 servers (26 Oct, updated 29 Oct 2026). Retrieved . ↩ ↩ ↩ ↩ ↩ ↩ ↩ ↩ ↩
  2. Unit 42 threat brief: CVE-2026-109618 and CVE-2026-109619 (updated 29 Oct 2026). Retrieved . ↩ ↩ ↩ ↩
  3. Palo Alto Networks advisory: impact of the PHP vulnerabilities on Palo Alto Networks products. Retrieved . ↩ ↩ ↩ ↩ ↩
  4. The PHP Foundation: today's PHP security release (21 Oct 2026). Retrieved . ↩ ↩
  5. PHP.net news archive 2026: security advisory of 21 Oct and session upload progress note of 23 Oct. Retrieved . ↩ ↩ ↩ ↩
  6. NVD: CVE-2026-109618, with CISA KEV dates. Retrieved . ↩
  7. NVD: CVE-2026-109619, with CISA KEV dates. Retrieved . ↩ ↩
  8. Calif: PHP2Shell write-up. Retrieved . ↩
  9. GHSA-w8hw-w9fx-j79w: RCE via OOM corruption (CVE-2026-109618). Retrieved . ↩ ↩
  10. Delft Threat Intelligence Lab: PHP2Shell in the wild (live, read 30 Oct 2026 10:52 UTC). Retrieved . ↩
  11. GreyNoise: PHP2SHELL activity 2026 (live, read 30 Oct 2026 10:45 UTC). Retrieved . ↩ ↩
  12. The Record: Limited reports of PHP bug exploitation emerge (29 Oct 2026). Retrieved . ↩
  13. AWS Security Blog: PHP2Shell exploitation prior to public disclosure in MadPot. Retrieved . ↩ ↩
  14. GHSA-6wmf-4rv5-p3rp: RCE via stale global state (CVE-2026-109619). Retrieved . ↩
  15. NVD: CVE-2026-46300 (Fragnesia), with CISA KEV dates. Retrieved . ↩

Published · Updated Report an error (support@agentum.cloud)