PoC fonctionnel de CVE-2026-52715 (GeoLeak): SQLi non authentifiée dans GEO my WordPress <= 4.5.5 via swlatlng/nelatlng. Laboratoire Docker + exploit time-based/boolean-based + exfiltration sans virgules dans le payload.
Preuve de concept éducative de GeoLeak (CVE-2026-52715), injection SQL non authentifiée (CVSS 9.3) dans le plugin GEO my WordPress <= 4.5.5 pour WordPress. Les paramètres
swlatlngetnelatlngdes limites de la carte sont interpolés sans assainissement dans la clause WHERE. Laboratoire Docker autonome + exploit avec techniques time-based, boolean-based et exfiltration caractère par caractère.
CVE-2026-52715 est une injection SQL (CWE-89) dans la fonction gmw_get_locations_within_boundaries_sql() du plugin GEO my WordPress, qui affecte toutes les versions <= 4.5.5 et est corrigée depuis la 4.5.5.1 (15 juin 2026). Elle a été découverte par le chercheur alvarodh5 et publiée via Patchstack.
La chaîne baptisée GeoLeak démontre comment, en partant uniquement d'un accès en lecture à n'importe quelle page publique contenant le shortcode [gmw], un attaquant peut :
swlatlng (ou nelatlng) de la chaîne de requête, sans cookies, sans nonce et sans authentification.SLEEP() (time-based blind) évalué pour chaque ligne de l'INNER JOIN avec wp_gmw_locations."total_results":N que le plugin lui-même intègre dans le JSON de configuration de la carte pour déduire des conditions booléennes (boolean-based blind).explode(',', ...)), à l'aide de CASE WHEN et de SUBSTRING(x FROM n FOR 1).Le résultat est une lecture arbitraire de la base de données WordPress : table wp_users (hashes de mots de passe), options de configuration, clés et données tierces stockées dans les plugins.
Dans la PoC, l'extraction complète de VERSION() de MariaDB est vérifiée uniquement avec des requêtes GET.
Ce dépôt contient du matériel strictement éducatif et défensif.
┌─────────────────────────────────────────────────────────────────────┐
│ 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 et awk pour l'exploitdocker-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
Paramètres configurables de l'exploit :
TARGET=http://localhost:3080 PAGE_ID=5 FORM_ID=1 SLEEP=5 ./poc/poc.sh
Accès à WordPress : http://localhost:3080 avec admin/admin. La page contenant le formulaire vulnérable est http://localhost:3080/?page_id=5.
Remarque : la ligne seed dans
wp_gmw_locationsest indispensable. La requête utilise un INNER JOIN contre cette table : sans lignes, le WHERE injecté n'est pas évalué etSLEEP()ne dort pas.
Sortie réelle de la dernière exécution contre le laboratoire (14 août 2026) :