Metadata-Version: 2.4
Name: wp2shell-detect
Version: 1.0.1
Summary: Blackbox, non-intrusive detector for wp2shell (WordPress core pre-auth RCE, CVE-2026-63030 / CVE-2026-60137).
Project-URL: Homepage, https://own2pwn.fr
Project-URL: Repository, https://github.com/own2pwn-fr/wp2shell-detect
Project-URL: Writeup, https://own2pwn.fr/articles/appsec/wp2shell-wordpress-rce
Author-email: own2pwn <contact@own2pwn.fr>
License: MIT License
        
        Copyright (c) 2026 own2pwn
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: cve,rce,scanner,security,vulnerability,wordpress,wp2shell
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Intended Audience :: Information Technology
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet :: WWW/HTTP :: Indexing/Search
Classifier: Topic :: Security
Requires-Python: >=3.8
Description-Content-Type: text/markdown

# wp2shell-detect

Blackbox, **non-intrusive** detector for **wp2shell** — the pre-authentication
RCE chain in WordPress core disclosed on 2026-07-17:

- **CVE-2026-63030** — route confusion in the REST batch endpoint
  (`/wp-json/batch/v1`): a sub-request whose path fails `wp_parse_url()` lands in
  the validation array but not the handler array, desynchronising the two.
- **CVE-2026-60137** — SQL injection in `WP_Query`'s `author__not_in` handling,
  reachable pre-auth through that route confusion.

Chained, they let an anonymous attacker forge an administrator account and drop a
plugin webshell — on a **default install**, no plugin or theme required.

Full technical writeup:
<https://own2pwn.fr/articles/appsec/wp2shell-wordpress-rce>

## What this tool does (and does not)

It **detects exposure**. It **does not exploit** anything. Every request it makes
is a normal, read-only request a crawler could send:

1. **Fingerprints the WordPress core version** from many public sources, so a
   hardened install that strips the `generator` tag is still identified: the
   `generator` meta tag, **core asset `?ver=`** (on `/wp-includes/` and
   `/wp-admin/` assets, which track core), the RSS feed generator (`?v=`),
   `/wp-links-opml.php`, the login page assets, `/wp-includes/version.php`,
   `readme.html`, and the `/wp-json/` index. Sources are cross-checked and a
   **confidence** (`high` when ≥2 agree) is reported.
2. **Compares** the version to the known-vulnerable ranges.
3. **Checks the REST batch route** with a benign `OPTIONS` request (and the REST
   index) — which returns the route schema *without ever invoking the handler* —
   to tell whether an edge mitigation is in place.
4. **Discovers headless WordPress back-ends.** If the target front isn't WP but
   references a WordPress host on the same domain (via CSP, the `Link` header or
   asset URLs — common with headless/Next.js fronts), the tool reports it, and
   `--discover` scans it too.

No request triggers the vulnerability. No `POST /wp-json/batch/v1`, no
`author_exclude`, no SQL. If the core version is hidden, the tool says so rather
than guessing (confirming wp2shell blindly would require exploiting it).

**Resilience:** retries with backoff, gzip/deflate decoding, `https→http`
fallback, cross-host redirect following, a browser-like User-Agent (overridable),
and parallel multi-target scanning.

## Vulnerable ranges

| Range | Exposure | Fixed in |
|-------|----------|----------|
| 6.8.0 – 6.8.5 | SQL injection only (no RCE) | 6.8.6 |
| 6.9.0 – 6.9.4 | **pre-auth RCE** | 6.9.5 |
| 7.0.0 – 7.0.1 | **pre-auth RCE** | 7.0.2 |

## Install

```bash
pip install wp2shell-detect
```

Or run it straight from source (single file, no dependencies, Python 3.8+):

```bash
git clone https://github.com/own2pwn-fr/wp2shell-detect
./wp2shell-detect/wp2shell_detect.py https://example.com
```

## Usage

Zero dependencies. Python 3.8+.

```bash
wp2shell-detect https://example.com
wp2shell-detect --json https://a.example https://b.example
wp2shell-detect --targets hosts.txt --workers 16   # parallel sweep
wp2shell-detect --discover https://front.example   # follow headless WP
```

(Installed from PyPI, the command is `wp2shell-detect`. From a clone, call
`./wp2shell_detect.py` with the same arguments.)

Options: `--json`, `--discover`, `--workers N`, `--timeout S`, `--user-agent UA`,
`--insecure`, `--targets FILE`. Exit code `2` if any target is found vulnerable
(handy in CI / cron sweeps).

### Headless WordPress

Modern sites often serve a JS/Next.js front on `www.` and keep WordPress on a
sibling host (`wordpress.`, `wp.`, `cms.`). Scanning `www.` then returns
`not WordPress` — correctly, because that host isn't WordPress. Point the scan at
the WordPress host, or pass `--discover` to have the tool find and scan it from
the front's CSP / `Link` header / asset URLs automatically.

Example:

```
[!!] https://blog.example.com  ->  VULNERABLE (pre-auth RCE)
      version : 6.9.3  (generator meta tag=6.9.3, RSS feed generator=6.9.3)
      batch   : reachable  (/wp-json/batch/v1)
      cves    : CVE-2026-63030, CVE-2026-60137
      note    : WordPress 6.9.3 is in the wp2shell pre-auth RCE range. REST batch endpoint reachable — no edge mitigation.
```

## Mitigation

Patch WordPress core to **6.8.6 / 6.9.5 / 7.0.2** or later. If patching must
wait, block the batch route at the edge (`/wp-json/batch/v1` and
`?rest_route=/batch/v1`) or via a must-use plugin hooking `rest_pre_dispatch`,
then audit for rogue admin accounts and unknown plugins.

## Legal

For authorised assessment only. Running this against systems you neither own nor
are mandated to test may be illegal in your jurisdiction. You are responsible for
how you use it.

## License

MIT. See [LICENSE](https://github.com/own2pwn-fr/wp2shell-detect/blob/main/LICENSE). By own2pwn.
