Skip to main content
wp2shell — the wordpress chain that lit the internet on fire
  1. MindSecSet/

wp2shell — the wordpress chain that lit the internet on fire

·846 words·4 mins·
Author
Virtue of Vague
Table of Contents

July 17, 2026. WordPress drops patches for two vulnerabilities. Within hours, mass scanning begins. Within a day, working PoCs land on GitHub. By the weekend, tens of thousands of exploitation attempts, over a hundred backdoor accounts, and a spot on CISA’s KEV list.

Two CVEs. One chain. Unauthenticated remote code execution on stock WordPress. No plugins needed.

what actually happened
#

Two vulnerabilities chained together:

CVE-2026-60137 — SQL injection in author__not_in. The value gets dropped directly into raw SQL. Requires authentication on its own. High severity, but contained.

CVE-2026-63030 — logic flaw in the REST batch API at /wp-json/batch/v1. Validation and execution run in separate loops. When one sub-request errors during validation, it gets removed from the validation array but not the execution array. The arrays desync by one position. Sub-request N executes under the permission context of sub-request N-1.

Chain them together? The batch confusion removes the auth requirement from the SQLi. Unauthenticated attacker reaches a protected endpoint, injects SQL, escalates to admin, drops a webshell, and cleans up. All in one request.

the timeline (so far)
#

WhenWhat
July 17, ~18:00 UTCPatches released (6.9.5, 7.0.2). Forced auto-updates enabled.
July 17, within hoursFirst honeypot exploitation. Mass scanning of /wp-json/batch/v1.
July 18Public PoC on GitHub. Full IPv4 scanning begins.
July 19IR engagements active. Webshells confirmed in the wild. CISA advisory.
July 20–22Exploitation ongoing. Tens of millions of unpatched sites globally.

the attack chain in plain english
#

Step 1 — Route confusion

Craft a sub-request that errors during validation. The batch handler drops it from the permission-check array but not from the execution array. Now every following sub-request runs with the wrong permissions. Auth-required endpoints become reachable without login.

Step 2 — SQL injection

With the auth gate gone, the author__not_in parameter accepts a raw string instead of an integer array. PHP type juggling skips sanitization, and the attacker’s value lands straight in the SQL WHERE clause. UNION injection reads admin password hashes from wp_users and writes to wp_posts and wp_options.

Step 3 — Customizer escalation to RCE

Forged customize_changeset and request database rows trick WordPress’s customizer preview into executing in the context of an existing admin (usually user ID 1). From there: create a rogue admin, install a webshell plugin, run arbitrary PHP, delete the evidence. Done.

what a Security analyst watches for
#

Forget complex queries for a moment. Here’s the signal:

Network: POST requests to /wp-json/batch/v1 or /?rest_route=/batch/v1. HTTP 207 Multi-Status is a high-fidelity indicator — the batch endpoint returns this on partial success. User-agent strings wp2shell and rezwp2shell are dead giveaways. Request bodies containing author__not_in, UNION ALL SELECT, or SLEEP( are the smoking gun.

Host: New admin accounts created after July 17. customize_changeset rows with suspiciously high parent IDs in wp_posts. PHP files sitting in wp-content/uploads/ — that directory should never have executable code. Webshell signatures like eval(base64_decode or system($_ are worth grepping for.

None of this is subtle. The batch API abuse lights up access logs. The SQL injection leaves fingerprints in request bodies. The post-exploitation artifacts persist until someone looks.

confirmed IOCs (as of July 22)
#

Exploitation IPs:

  • 34.81.132[.]62
  • 79.177.131[.]206
  • 15.157.135[.]170
  • 94.100.52[.]128
  • 172.235.128[.]52

Webshell hashes (SHA1):

  • 2a1410d8e2a8337ac2171cedea8c0fdc47c647a0
  • 58eca847e9eae9e6b08cc211f1559817b71bc4cc
  • ebea44890f434d5d67ede22009a3f4bb5cac33f8
  • d9a220c8039f1c4d72cae7ccb8b3a33dec8815be
  • e9756e2338f84746007235e4cab7a70d5b3ca47f

Rogue accounts:

  • Username prefix: wp2_*, w2s_*
  • Email domains: @wp2shell.invalid, @wp2shell.shellcode.lol

post-exploitation behavior
#

Attackers aren’t just dropping shells and leaving. Observed activity includes:

  • Malicious plugin uploads via /wp-admin/update.php?action=upload-plugin
  • User enumeration through /wp-json/wp/v2/users?context=edit
  • LFI attempts targeting wp-config.php for database credentials
  • Admin panel access confirmed from attacker IPs

One webshell found in the wild was a 150KB “CMSmap” disguised as a legitimate plugin — full GUI, file manager, DB access, port scanner. Obfuscated with hex-encoded, gzip-compressed base64. That’s not script kiddie territory. That’s operational infrastructure.

MITRE ATT&CK quick map
#

TacticTechnique
Initial AccessT1190 — Exploit Public-Facing Application
ExecutionT1059.004 — Unix Shell
PersistenceT1505.003 — Web Shell
Privilege EscalationT1548 — Abuse Elevation Control Mechanism
DiscoveryT1087.001 — Account Discovery
Credential AccessT1003 — OS Credential Dumping
Defense EvasionT1027 — Obfuscated Files

what to do right now
#

Patch. WordPress 6.9.5, 7.0.2, or newer. On 6.8.x (SQLi only), apply 6.8.6. Forced auto-updates are active — don’t disable them.

If patching isn’t immediate, block at the WAF:

location ~* /wp-json/batch/ { return 403; }
location ~* [?&]rest_route=/batch { return 403; }

Check for compromise. Look for new admin accounts created after July 17. Sweep for PHP files in uploads. If you find any, assume full compromise and initiate IR.

why this one matters
#

WordPress vulnerabilities are common. Most need a plugin. Most need authentication. Most are patched before mass exploitation.

This one was different. Stock WordPress. No auth required. Weaponized within hours. The chain — two vulnerabilities, neither catastrophic alone, devastating together — is a reminder that the gaps between systems matter as much as the systems themselves.

If you’re defending WordPress, run the checks. If you’re a Security analyst, tune your alerts for that batch endpoint. The window is still open.

Maximum effort.

Sources: Searchlight Cyber, Wiz Research, Eye Security, Brandefense, CISA KEV. IOCs confirmed as of July 22, 2026.

Related