Skip to content

zi3lak/wp2shell_scanner

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

wp2shell_scanner

smoke License: MIT Python 3.7+ Mode: detection-only CVE-2026-63030 · CVE-2026-60137

Non-intrusive detection scanner for recent WordPress core vulnerabilities — including the wp2shell pre-authentication RCE chain.

wp2shell_scanner.py fingerprints a WordPress site's core version and reads its publicly advertised REST API surface, then classifies each tracked core CVE independently against the detected version. Verdicts are branch-aware — e.g. a 6.8.x site is correctly reported as exposed to the SQL-injection CVE but not to the full RCE chain. It detects only: no exploit payload is ever sent. Single file, one dependency (requests), CI-friendly exit codes, and client-ready HTML / JSON / e-mail reports.

⚠️ Authorised use only. Scan systems you own or are explicitly authorised (in writing) to test. The scanner sends an identifying User-Agent so blue teams can attribute the traffic — it does not hide.


Tracked vulnerabilities (WordPress core)

CVE Weakness Access Affected core Fixed in
CVE-2026-63030 — wp2shell CWE-436 — REST batch route confusion → RCE (Critical, GHSA-ff9f-jf42-662q) Unauthenticated 6.9.06.9.4, 7.0.07.0.1 6.9.5, 7.0.2
CVE-2026-60137 CWE-89 — SQL injection in WP_Query author__not_in (High) Unauthenticated 6.8.06.8.5, 6.9.06.9.4, 7.0.07.0.1 6.8.6, 6.9.5, 7.0.2
CVE-2026-3906 CWE-862 — Notes REST API missing authorization (Moderate, CVSS 4.3, GHSA-6x83-fcf5-r65g) Subscriber+ 6.9.06.9.3 6.9.4

The wp2shell RCE chain = CVE-2026-63030 + CVE-2026-60137 together → pre-auth remote code execution on a default install. The scanner reports the chain as exposed only when both CVEs classify as vulnerable for the detected version.

Branch nuances the scanner gets right:

  • 6.8.x carries the SQL injection (CVE-2026-60137) only — not the RCE chain.
  • CVE-2026-3906 was only partially fixed in 6.9.2/6.9.3 and fully fixed in 6.9.4, while the wp2shell chain isn't closed until 6.9.5. So a 6.9.4 site reads patched for the Notes bug but still vulnerable to the RCE chain.

Operationally important: technical write-ups and a working PoC for wp2shell are already public. Version detection is now the absolute minimum — the priority is patching. Updating closes the vulnerable path but does not remove a backdoor planted before the patch — hence the compromise-assessment step in the report.

Scope

This is a core-version scanner. Plugin and theme CVEs — the large majority of the WPScan / Patchstack catalogue — require a live, curated feed and per-plugin version enumeration, and are intentionally out of scope here. Within its lane (recent WordPress core CVEs), it aims to be precise and branch-accurate rather than to duplicate a commercial vulnerability database.


What the scanner does

  • Passive WordPress fingerprinting across four public version vectors:
    • <meta name="generator"> on the homepage
    • /readme.html
    • RSS / Atom feed <generator> tag
    • /wp-links-opml.php (OPML)
  • Cross-checks the vectors. If they disagree on the version, or a pre-release build (beta/RC/alpha) is seen, the verdict is forced to UNKNOWN — the scanner never reports a possibly-false Patched from conflicting evidence.
  • REST API surface discovery — reads /wp-json/ to see whether WordPress advertises the batch/v1 namespace in its REST index. This confirms the namespace is registered, not that the endpoint is reachable through a WAF. No batch request and no payload are sent.
  • Per-CVE verdict — the detected version is classified independently against each tracked CVE (branch-aware), plus outputs:
    • a client-ready HTML report (print → PDF),
    • a JSON record (pipeline/EAV-friendly),
    • a draft notification e-mail.

What it explicitly does not do

It does not exploit anything. No SQL-injection payload, no batch-route-confusion request, no attempt to execute code or read data. Detection is version-based plus a passive read of the publicly advertised API surface.


Install

pip install requests

Usage

# single target
python3 wp2shell_scanner.py -t https://site.example --authorized

# list of targets (one per line, # comments allowed)
python3 wp2shell_scanner.py -T scope.txt --authorized -o ./reports

# preview the output formats with synthetic data — no network, no auth needed
python3 wp2shell_scanner.py --demo -o ./reports

Flags

Flag Meaning
-t, --target Single target URL or host
-T, --targets-file File with one target per line
--demo Generate a SAMPLE report/e-mail from synthetic data (no network)
-o, --output-dir Output directory (default ./wp2shell_reports)
--formats Comma list: json,html,email (default: all)
--authorized Authorisation gate — required for live scans
--timeout HTTP timeout in seconds (default 12)
--delay Seconds between targets (be polite; default 1.0)
--insecure Do not verify TLS certificates
--quiet Suppress the console summary

The --authorized flag is an explicit authorisation gate — live scans refuse to run without it.

Exit codes (CI-friendly)

Code Meaning
2 At least one target vulnerable
1 At least one target inconclusive / error
0 Clean (patched / not affected / not WordPress)

Configuration

The notification e-mail recipient is the CSSLTD_CONTACT constant near the top of the script (default ops@cyberssl.co.uk). Edit it to your own intake address.


Verdicts

Verdict Meaning
VULNERABLE Detected version falls inside an affected range — patch immediately
PATCHED On a fixed release; not exposed to this chain
NOT_AFFECTED Version predates the flaw (< 6.9.0)
UNKNOWN Version could not be confirmed, vectors disagreed, or a pre-release build was seen — verify manually
NOT_WORDPRESS No WordPress fingerprint found

Example output

The examples/ directory contains synthetic (--demo) output for a fictional vulnerable host (example.com, WordPress 6.9.1 — exposed to all three tracked CVEs):

These are generated from fabricated data to illustrate the report format. They are not the result of scanning any real site.


Remediation (as emitted in the report)

  1. Take a verified backup (DB + full file tree) first.
  2. Update WordPress core to the fixed release for your branch — 6.8.6 / 6.9.4 / 6.9.5 / 7.0.2 — or later.
  3. Confirm the site and admin still work.
  4. Assume compromise if the host was exposed while vulnerable — run a compromise assessment across themes, plugins, uploads/, wp-config.php, wp-cron, and admin accounts; run file-integrity checks against known-good core.
  5. Add defence-in-depth at the edge (WAF rules, restrict /wp-json/batch/v1).
  6. Rotate secrets (auth salts, admin/DB passwords, API keys) if compromise is suspected.
  7. Re-scan to confirm the verdict now reads Patched.

References


Disclaimer

This tool is for authorised security testing only. You are responsible for ensuring you have permission to scan any target. Unauthorised scanning may be unlawful. The authors accept no liability for misuse.

About

Non-intrusive detection scanner for the WordPress wp2shell pre-auth RCE chain (CVE-2026-63030 + CVE-2026-60137). Detection-only, no exploitation.

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages