Skip to main content
Agency Program 50% cashback. Exclusive discounts. Priority support. Built for growing agencies. 50% cashback. Exclusive discounts. Priority support. Built for growing agencies. Speak to the team Join free

php2shell in the Wild: What Attackers Tried in the First 14 Hours, and What Stopped Them

Attacks on php2shell reached InstaWP-hosted sites 2h20m after disclosure. None succeeded. What each campaign tried, and which PHP setting stopped it.

VS
Vikas Singhal
Founder, InstaWP
Updated Oct 22, 2026 9 min read

Scripted attacks on php2shell reached InstaWP-hosted WordPress sites 2 hours 20 minutes after PHP published the technical details of CVE-2026-109618 and CVE-2026-109619 on 21 October 2026, and an exploitation-shaped campaign followed 72 minutes later. None of these attempts succeeded. No PHP worker crashed or ran out of memory at request startup, and no shell was spawned. Every attack wave arrived after a defence was already in place.

This is InstaWP’s read-only analysis of its server logs from 20 to 22 October. The php2shell live status page covers the bugs and what customers need to do. This post covers what attackers sent, and which setting stopped each attempt.

Data window: 20 October 2026, 00:00 UTC to 22 October 2026, about 05:15 UTC. Analysis completed 22 October 2026.
Key takeaways
  • The first new campaign came 2 h 20 m after disclosure. It probed for session upload-progress, which InstaWP had switched off at about 08:35 UTC.
  • The exploitation-shaped wave came 3 h 32 m after disclosure. PHP’s nesting limit, lowered to 32 an hour earlier, discarded its over-nested fields.
  • No attempt succeeded. Zero startup out-of-memory errors, zero heap corruption, no worker crash near any attack burst.
  • 23% of that campaign’s main wave landed before patched PHP. The mitigation and hardening stopped those alone.

How quickly did attackers start using php2shell?

Within hours. PHP published the technical details at 14:00 UTC on 21 October 2026, the first scripted wave reached InstaWP-hosted sites at 16:20 UTC, and the exploitation-shaped wave followed at 17:32 UTC. By then two of InstaWP’s three defences were live, and patched PHP arrived 21 minutes later.

When (UTC)DefenceAttack
20 Oct, 20:32PHP gives advance notice of the release, with no technical details
21 Oct, ~08:35InstaWP switches off session upload-progress on every managed server and verifies it on the running PHP workers
21 Oct, 11:42 and 12:19Two background multipart sprays (C and D) are already running, before any details are public
21 Oct, 14:00PHP releases the fixes and an advisory with full technical details
21 Oct, 16:20Campaign B, an upload-progress scanner, starts
21 Oct, ~16:30InstaWP lowers max_input_nesting_level to 32 on every PHP pool, and sets fatal_error_backtraces=0 on PHP 8.5
21 Oct, 17:32Campaign A, a deep-nesting kit, starts. Its main wave runs until 18:30.
21 Oct, 17:53Patched PHP rolled out
21 Oct 21:00 to 22 Oct 04:00C and D roughly triple their rate, B keeps probing, and A trickles on at about one site an hour

Read it by matching each attack to the defence above it. Campaign B looked for upload-progress, off for almost eight hours by then. Campaign A relied on deeply nested input, capped an hour earlier.

Total upload traffic stayed flat, because real media uploads dominate it. The signal was multipart requests to a site’s homepage, where no upload form lives: overnight they ran at three to four times the pre-disclosure rate.

Both attack waves started after the defence they target was already live Requests per hour from campaigns A and B, 21 Oct 11:00 to 22 Oct 04:00 UTC. Session upload-progress was off from about 08:35. Campaign A, deep-nesting kit Campaign B, upload-progress scanner 0 100 200 300 14:00 PHP disclosure ~16:30 nesting limit 32 17:53 patched PHP 11:00 UTC: campaign A 0 requests, campaign B 0 requests 11:00 12:00 UTC: campaign A 0 requests, campaign B 0 requests 13:00 UTC: campaign A 0 requests, campaign B 0 requests 14:00 UTC: campaign A 0 requests, campaign B 0 requests 14:00 15:00 UTC: campaign A 0 requests, campaign B 0 requests 16:00 UTC: campaign A 0 requests, campaign B 69 requests 17:00 UTC: campaign A 139 requests, campaign B 18 requests 17:00 18:00 UTC: campaign A 286 requests, campaign B 18 requests 19:00 UTC: campaign A 0 requests, campaign B 15 requests 20:00 UTC: campaign A 0 requests, campaign B 6 requests 20:00 21:00 UTC: campaign A 8 requests, campaign B 9 requests 22:00 UTC: campaign A 0 requests, campaign B 48 requests 23:00 UTC: campaign A 3 requests, campaign B 54 requests 23:00 00:00 UTC: campaign A 0 requests, campaign B 45 requests 01:00 UTC: campaign A 3 requests, campaign B 57 requests 02:00 UTC: campaign A 0 requests, campaign B 45 requests 02:00 03:00 UTC: campaign A 3 requests, campaign B 56 requests 04:00 UTC: campaign A 3 requests, campaign B 27 requests 22 Oct 21 Oct 139 286 B keeps probing overnight, up to 57 an hour
The two waves that matter arrived 2 h 20 m and 3 h 32 m after disclosure, and both met a setting that was already live. Source: InstaWP origin server logs, read-only analysis of 22 October 2026. Hover a bar for its exact count.

What did each php2shell campaign try, and what stopped it?

Four scripted campaigns sent multipart POST requests to site homepages: one exploitation-shaped, one fingerprinting, and two background sprays that predate the disclosure. Each met a control that was already live. Payloads are described by behaviour only.

CampaignFirst seen (UTC)What it didWhat stopped it
A: deep-nesting kit21 Oct, 17:32 (3 h 32 m after disclosure)Per site, a short burst of large multipart requests with deeply nested field names, followed by small follow-up requestsThe nesting limit of 32 made PHP discard the over-nested fields while parsing. Sites served their normal homepage.
B: upload-progress scanner21 Oct, 16:20 (2 h 20 m after disclosure)Uploads sized around common default body limits, checking how the server handles them and whether session upload-progress is exposedUpload-progress was already off, so there was nothing to find
C: background spray21 Oct, 12:19 (before disclosure)Small requests followed by padded multipart bodies that look built to slip past body inspectionNo effect. No startup warnings, memory errors or crashes, and normal responses.
D: background spray21 Oct, 11:42 (before disclosure)Pairs of fixed-size multipart requests, most likely a generic WordPress plugin exploit sweepNo side effects at all

Campaign A: the one that looked like exploitation

Campaign A’s traffic matches the memory-exhaustion strategy in PHP’s advisory for CVE-2026-109618 (deeply nested field names), paired with the follow-up requests CVE-2026-109619 needs. It was one tool with a fixed request pattern, run from rented cloud servers that rotated to an almost fresh source address per site. It behaved like a spray that hits each site once. Real heap grooming needs many tries against one PHP worker, and campaign A sent at most two heavy requests to any site.

Sites answered with their ordinary homepage and HTTP 200, the same size as a normal visit, while PHP logged an “Input variable nesting level exceeded 32” warning hundreds of times per request. 98 of the 428 main-wave requests (23%) landed before patched PHP at 17:53 UTC, and the mitigation and hardening stopped those on their own.

Campaigns B, C and D: scanning and background noise

Campaign B identifies itself as an authorized scanner. It is not one of InstaWP’s tools, and the label is only the sender’s claim. It found nothing and was still probing when the analysis closed. Campaigns C and D were running before PHP published any detail, roughly doubled or tripled their rate overnight, and left no side effect in PHP’s logs. D looks like a generic WordPress plugin sweep that happens to use multipart requests.

Let the host carry the PHP patchingOn InstaWP managed WordPress hosting, the mitigation, the hardening and the patched PHP all landed without customers changing a setting.
Explore managed WordPress hosting →

How does InstaWP know none of these attempts succeeded?

Because every side effect a working php2shell exploit would leave is missing. InstaWP checked each signal PHP’s advisories point to, on every InstaWP-managed hosting server:

  • Zero out-of-memory fatals at request startup. Every memory fatal in the window came from ordinary plugin or theme code.
  • Zero zend_mm_heap corrupted errors.
  • No PHP worker exited within two minutes of an attack burst. The only two signal crashes were nowhere near attack traffic.
  • No upload-progress session keys in any request’s query string.
  • No suspicious shells, cron jobs or outbound connections. Shells launched from PHP traced to normal behaviour such as sending mail, new cron entries were customers’ own, and outbound connections went only to web and database ports.
  • No new PHP files planted through php2shell. Targeted sites were spot-checked for new PHP files. None of these attempts compromised a site.

What can’t InstaWP see?

Quite a lot. InstaWP does not log request bodies, so every campaign here is described from request size, timing, order and the side effects PHP recorded: campaign A matches the advisory’s nested-names strategy, but its payload cannot be proven. InstaWP’s log of multipart requests started at about 11:40 UTC on 21 October, so there is no multipart visibility for 20 October and only a 2 h 20 m baseline before disclosure.

Before about 16:30 the nesting limit was PHP’s default of 64, so a shallower probe earlier in the day would have parsed silently. Requests blocked at the CDN edge never reached the servers, which makes every count here a floor. And the check for new PHP files was deliberately bounded, so a file hidden deep inside a plugin folder with backdated timestamps would be missed.

What should you do if you run PHP yourself?

Patch within hours, and keep the hardening afterwards. These four steps held on InstaWP through the first 14 hours of attacks:

  • Apply PHP’s interim mitigations the moment they are published. Set session.upload_progress.enabled=0 in php.ini or the FPM pool and restart every worker. PHP’s advisory for CVE-2026-109619 notes that ini_set() and .user.ini do not help.
  • Add the hardening, not just the mitigation. PHP’s advisory for CVE-2026-109618 suggests limiting input nesting depth. InstaWP lowered max_input_nesting_level from 64 to 32, which neutralised campaign A. On PHP 8.5, also set fatal_error_backtraces=0.
  • Keep upload-progress off after you patch. Campaign B was still probing for it hours after the patch.
  • Patch fast. Move to PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35, or your distribution’s patched package. 23% of campaign A’s main wave arrived before InstaWP’s patch.

To spot this traffic, watch multipart requests to the homepage, not total POST volume: the attacks were small. If your site is hosted on InstaWP, you don’t need to change anything, because InstaWP applied every layer above. The php2shell status page has the full customer guidance, and the InstaWP guide to configuring PHP covers changing PHP versions.

The verdict

Attackers moved on php2shell within hours of PHP’s 21 October 2026 disclosure, and none of their attempts against InstaWP-hosted sites succeeded. The order of events did the work: upload-progress was off before the details were public, the nesting limit was down before the deep-nesting kit arrived, and patched PHP followed 21 minutes later.

Frequently asked questions

Was php2shell exploited in the wild?

InstaWP saw exploitation attempts within hours of PHP’s disclosure on 21 October 2026, including one campaign whose traffic matches the deep-nesting memory-exhaustion strategy in PHP’s advisory. None of the attempts against InstaWP-hosted sites succeeded.

How soon after disclosure did php2shell attacks start?

On InstaWP, an upload-progress scanner started 2 hours 20 minutes after PHP published the details at 14:00 UTC on 21 October 2026, and the exploitation-shaped deep-nesting campaign started 3 hours 32 minutes after.

Does max_input_nesting_level protect against php2shell?

Lowering max_input_nesting_level to 32 made PHP discard the over-nested fields that the deep-nesting campaign relied on, so it blocked that route on InstaWP. It is hardening, not a fix: install patched PHP as well.

Should session upload-progress stay off after patching PHP?

InstaWP keeps session upload-progress off after patching as extra protection, and PHP recommends keeping the interim measures in place. On InstaWP, a scanner was still probing for the feature hours after the patch was out.

Do InstaWP customers need to do anything about php2shell?

No. InstaWP applied the interim mitigation, the hardening and patched PHP on InstaWP-managed servers on 21 October 2026. The php2shell status page has the full customer guidance.

References

VS
Vikas Singhal
Founder, InstaWP

Vikas builds tools that take the friction out of WordPress development. He writes about WP-CLI, dev workflows, and running WordPress at agency scale.