Observations

Scanners hit websites 15 hours before the PHP2Shell patch existed

Between 20 and 22 October, around one in five of the sites Salience monitors received requests shaped like the PHP2Shell exploit. The first arrived 15 hours before PHP released the fix. Nearly all were refused at the edge, so they appear in server logs and nowhere else.

Carl Hendy

Carl Hendy, Co-founderPublished

15 h
between the first exploit-shaped request and the PHP release22:30 UTC on 20 October against 14:00 UTC on 21 October
22%
of monitored sites received exploit-shaped requestswithin 36 hours of the first one
5
scanner tools named the bug in their user agentfirst seen 09:18 UTC on 21 October
4%
of monitored sites answered one of these requests with a 2xxboth run PHP; both owners were contacted

Server logs record the request line, the headers, the body size and the response. They do not record the body itself, so no single request below can be proven to be an exploit. What the logs do show is the shape: a multipart POST of a particular size to a particular path, the response code it got, and in five cases a user agent that names the vulnerability.

What PHP2Shell is

PHP2Shell is the name given to two remote code execution bugs in the PHP runtime, CVE-2026-109618 and CVE-2026-109619, both rated 9.2 on CVSS v4.0. They affect every PHP version since 5.4 and every way of serving PHP, including PHP-FPM, mod_php, php-cgi, FrankenPHP and LiteSpeed. The flaws are in the engine, so a site is exposed whatever its own code does.

The CVE identifiers circulated on Hacker News and social media on 20 October. The PHP security team published an advance notice that day for a release at 14:00 UTC on 21 October. The fixed versions are PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35, with source patches for 7.4, 8.0 and 8.1.

Every known trigger is a multipart/form-data request, the format browsers use for file uploads. PHP parses that body before any application code runs. Cloudflare reported early attack attempts at 07:43 UTC on 21 October, before the release, and Amazon's honeypot network recorded an attempt on 17 October, four days before disclosure. Sansec later reported that the public proof-of-concept exploits did not work against a default PHP installation and that mass exploitation looked less likely than first expected.

When the requests arrived

The chart counts distinct sources per hour sending exploit-shaped requests across the monitored sites.

246
PHP releaseWed 14:00 UTC
before the release
first request15 hours earlier
Wed 21 OctThu 22 Oct
Distinct sources per hour sending exploit-shaped requests across the sites Salience monitors, 20 October 20:00 UTC to 22 October 07:00 UTC. Hover a column for the hour and count.

The first exploit-shaped request arrived at 22:30 UTC on 20 October, about 19 hours after the CVE identifiers circulated and 15 hours before the release. Named scanners started at 09:18 UTC on 21 October. The busiest hours were 21:00 and 22:00 UTC on 21 October, seven and eight hours after the release, with a second run between 04:00 and 07:00 UTC on 22 October.

Five scanners named the bug in their user agent

Five distinct tools identified themselves in the User-Agent header. Two of them carry the words "authorized audit" or "authorized security assessment" in the string. They came from hosting providers in the United States, Belgium, Switzerland, India and Germany.

User agentFirst seen (UTC)
php2shell-10961821 October
php2shell-ver… (the string is cut short in the log)21 October
php2shell-masscheck/1.0 (authorized-audit)21 October
php2shell-scan/2.0 (authorized-security-assessment)21 October
shellflow-php2shell/1.021 October

The earliest of the five was logged at 09:18 UTC on 21 October, just under five hours before the fixed PHP versions existed.

What the exploit-shaped requests looked like

The requests that match the published technique are oversized multipart POSTs to paths that PHP handles before application code: the site root, index.php and the WordPress REST batch route. Body sizes ran from 26 KB to 1 MB, often in pairs.

  • 22:30 UTC, 20 October: a French /24 address block posted bodies of 131 KB, 262 KB and 525 KB to the root of one site. The same block repeated the pattern against a second site the following night.
  • Other sources sent paired 26 KB and 65 KB bodies to one site's root. The paired sizes match the two-request technique the researchers describe.
  • 1 MB bodies went to index.php and to the WordPress REST batch route on two sites.

How the sites responded

Within 36 hours of the first request, 22% of the monitored sites had received at least one oversized POST matching the pattern. Most of the requests were refused at the CDN or web server before they reached any application.

  1. Refused at the edge (403, 404, 405 or 499)80%

    of the sites that received exploit-shaped requests

  2. Answered 2xx20%

    two PHP sites: one returned 200 to four 1 MB POSTs at its root at 06:51 UTC on 22 October, the other returned 202 to 1 MB POSTs on index.php twice

Response to exploit-shaped POSTs, by share of the sites that received them, 20 to 22 October 2026.

A 2xx response is not proof of compromise. It shows that the request reached PHP and was parsed. Both owners were told the same day and asked to update to a fixed version.

Background PHP probing did not rise

The PHP2Shell traffic sat on top of the usual probing and did not change its level. POST requests aimed at PHP paths across the monitored sites ran about 60% above the previous week's daily midpoint on 20 October, about 30% above on 21 October, and 22 October was on course to land inside the previous week's range. Hacking-probe alerts on 21 October were below the 20 October level.

The 20 October rise had a separate cause. A password-spraying botnet made 7,163 login attempts against wp-login.php from 6,018 IP addresses in one day, across about a quarter of the monitored sites.

Why this only shows up in server logs

Four in five of the sites that received these requests refused them at the CDN or web server. A request refused there never runs application code, never loads a page and never fires an analytics tag. Google Analytics does not see it. Search Console does not report it. The web server or CDN log is the only record that it happened, which is where the security monitoring in Salience reads from.

The sites hit were ordinary small and medium business sites. The security and threat detection guide covers how to read this kind of traffic in your own logs.

What to do

  1. 01Update PHP to 8.5.12, 8.4.27, 8.3.36 or 8.2.35. On 8.1 or older, take the backported package from your distribution or the PHP security team's source patch. If a hosting provider manages PHP, ask which build they run.
  2. 02If updating has to wait, Sansec published web server rules that reject multipart/form-data requests until PHP is fixed. They break file uploads and some checkout forms, so test after adding them and remove them once PHP is updated.
  3. 03Search your logs from 17 October onwards for POST requests with large bodies to the site root, index.php or /wp-json/ batch routes, and for user agents containing "php2shell". A 2xx on any of them is a reason to check the server.
  4. 04Check which layer answered. A 403 or 404 from the CDN means the request never reached PHP. A 200 or 202 from the origin means it did.

Sources

Your logs already show what Google and the AI crawlers are doing.

Free plan, no card, about ten minutes to your first request.