Skip to content

Back to the catalog

gichirimaku/wp2shell-PoC
github.comrepo

gichirimaku/wp2shell-PoC

wp2shell-PoC is a Python proof-of-concept exploiting a pre-authentication RCE chain in WordPress core, combining CVE-2026-63030 (REST API batch route confusion) and CVE-2026-60137 (SQL injection in WP_Query). It demonstrates escalation from the route-desync bug through blind SQLi, customize_changeset forgery, and hook re-entry to administrator account creation and arbitrary command execution via a malicious plugin upload. The tool supports vulnerability checking, data extraction (union, error-based, blind techniques), and full shell access with or without existing admin credentials.

TL;DR Python PoC chains two WordPress core CVEs into unauthenticated admin takeover and RCE.
Document

What it is

wp2shell-PoC is a Python 3.8+ script by gichirimaku for the WordPress core chain CVE-2026-63030 (route confusion in the batch REST endpoint) and CVE-2026-60137 (SQL injection in WP_Query). The chain gives unauthenticated remote code execution. The README labels it for educational and bug bounty use in controlled environments. It links two write-ups: one from slcyber.io and one from Picus Security.

How it works

/wp-json/batch/v1 tracks sub-requests in parallel $matches and $validation arrays indexed by position. A sub-request with a malformed path such as http://: is appended to $validation but skipped for $matches by a continue. Later sub-requests then run under the handler meant for the next one, which skips schema validation and permission checks.

The chain then proceeds in these steps:

  1. An outer batch bypasses the method allow-list that normally blocks GET.
  2. An inner batch sends a scalar author_exclude string to GET /wp/v2/posts. WP_Query interpolates it into SQL, giving a UNION-based blind injection.
  3. The injection returns forged WP_Post objects that WordPress caches in memory. Their [embed] shortcodes cause real oembed_cache rows to be written.
  4. A forged customize_changeset post carrying "user_id": 1 is applied. A cycle-detection gadget triggers wp_update_post() without overwriting the payload, so the request temporarily acts as the administrator.
  5. A fabricated post with status parse and type request fires parse_request, which replays the batch with the assumed role. POST /wp/v2/users now succeeds and creates an admin.
  6. The attacker logs in as that admin and uploads a malicious plugin to run commands.

Preconditions / Affected

The target needs only to expose the REST batch endpoint of a vulnerable WordPress core. The page gives no affected or fixed version numbers. Error-based extraction needs MySQL errors reflected (for example WP_DEBUG_DISPLAY on). Union and blind extraction do not.

What to do

The README's check mode sends a benign probe that detects the route confusion without running SQLi payloads:

wp2shell.py http://victim.com

A vulnerable target returns HTTP 207 with the error patterns parse_path_failed, block_cannot_read and rest_batch_not_allowed. These strings and requests to /wp-json/batch/v1 containing http://: are usable as log or WAF detection markers. --confirm-sqli adds an active payload, trying UNION reflection and then timing probes.

Beyond checking, the tool has read modes (--read, with --preset users for logins and hashes) and a shell mode (--shell) that runs the full chain with or without admin credentials. Use these only on systems you are authorized to test. Read the linked advisories for patch guidance, since the README names no fix.

Caveats

The README says the uploaded webshell and any generated admin account are removed automatically. That cleanup is the tool's claim and is not verified here. The cache-poisoning step writes real oembed_cache rows, so the chain is not purely in-memory. The page describes the read paths as read-only.

Organisations named here

  • route confusion

CVEs named here

  • CVE-2026-63030
  • CVE-2026-60137

Technologies named here

  • wp2shell-poc
  • WordPress Core
  • WordPress
  • Python

Techniques named here

  • REST batch route confusion
  • UNION-based blind SQL injection via WP_Query
  • Cache poisoning via forged WP_Post objects
  • Changeset escalation to assume admin identity
  • Hook re-entry via parse_request
  • Post-exploitation RCE via malicious plugin upload
  • SQL injection