Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
CVE-2026-76904 — Python scripts for inventorying GeoServer WFS endpoints and verifying time-based SQL injection vulnerabilities in PostGIS/GeoTools, with a dedicated PoC mode for authorized testing. | Kitploit
Tools/GitHubGitHub/bickzero93/cve-2026-76904
Vulnerability AnalysisExploitationWeb Application ExploitationInformation GatheringPenetration Testing
GitHubbickzero93/cve-2026-76904

CVE-2026-76904

Python scripts for inventorying GeoServer WFS endpoints and verifying time-based SQL injection vulnerabilities in PostGIS/GeoTools, with a dedicated PoC mode for authorized testing.

Repository anzeigen
vor 1 TagNoch nicht geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

GeoServer WFS Inventory und autorisierte Verifikation

Dieses Repository enthält zwei Python-Skripte für die Untersuchung von GeoServer-WFS-Endpunkten.

Übersicht

wfs_inventory.py

Zweck: Layer, XSD-Felder und WFS-Werte inventarisieren sowie Kandidaten optional über eine zeitbasierte Prüfung verifizieren.

Ausführbeispiele:

root@kitploit:~
python3 wfs_inventory.py --url https://HOST --valid-fields 4
root@kitploit:~
python3 wfs_inventory.py --url https://HOST --valid-fields 4 --sleep 1 --confirm-sleep 5 --candidate-scope auto --timing-result-type auto
root@kitploit:~
python3 wfs_inventory.py --url https://HOST --layer namespace:layer --sleep 1 --confirm-sleep 5 --valid-diagnose output.txt

geoserver_sqli_working.py

Zweck: Kombinierter Einstiegspunkt für die Inventur sowie ein separater PoC-Modus.

Ausführbeispiele:

root@kitploit:~
python3 geoserver_sqli_working.py --target https://HOST --valid-fields 4 --sleep 1 --confirm-sleep 5
root@kitploit:~
python3 geoserver_sqli_working.py --target https://HOST/geoserver/wfs --typename namespace:layer --field_name FIELD --sleep 5
root@kitploit:~
python3 geoserver_sqli_working.py --target https://HOST/geoserver/wfs --typename namespace:layer --field_name FIELD --sleep 5 --query "SELECT current_database()"

Wichtiger Hinweis: Die zeitbasierte Prüfung und der PoC-Modus dürfen nur gegen Systeme verwendet werden, für die eine ausdrückliche Testfreigabe vorliegt. Der normale Inventurmodus verwendet ausschließlich reguläre WFS-Operationen.

Voraussetzungen

  • Python 3.10 oder neuer
  • Keine zusätzlichen Python-Pakete; beide Skripte verwenden nur die Standardbibliothek
  • Netzwerkzugriff auf den WFS-Endpunkt

Optional ausführbar machen:

root@kitploit:~
chmod +x wfs_inventory.py geoserver_sqli_working.py

Schnellstart

Kandidaten über reguläre WFS-Abfragen suchen

root@kitploit:~
python3 wfs_inventory.py \
  --url https://HOST \
  --valid-fields 4

Der Standardpfad /geoserver/wfs wird automatisch ergänzt. Folgende Angaben sind daher gleichwertig:

root@kitploit:~
https://HOST
https://HOST/geoserver
https://HOST/geoserver/wfs

Bei einer abweichenden Installation muss der vollständige WFS-Pfad angegeben werden.

Kandidaten mit einer zeitbasierten Prüfung verifizieren

Nur für ausdrücklich autorisierte Systeme:

root@kitploit:~
python3 wfs_inventory.py \
  --url https://HOST \
  --valid-fields 4 \
  --sleep 1

Während der Prüfung erscheint pro Kandidat eine Messung auf stderr:

root@kitploit:~
[sleep-check] phase=screen typeName=namespace:layer field_name=FIELD resultType=hits baseline=0.120s test=1.128s delta=1.008s passed=true
[sleep-check] phase=confirm typeName=namespace:layer field_name=FIELD resultType=hits requested=3s baseline=0.118s test=3.125s delta=3.007s vulnerable=true

Ein bestandener Screen ist noch kein positiver Befund. Nur wenn die zweite, längere Messung ebenfalls besteht, wird ein Parameterblock ausgegeben.

Diagnose in eine Datei schreiben

root@kitploit:~
python3 wfs_inventory.py \
  --url https://HOST \
  --valid-fields 4 \
  --sleep 1 \
  --valid-diagnose output.txt

--valid-diagnose FILE aktiviert automatisch die ausführliche Diagnose und schreibt sie in die angegebene Datei.

Ablauf des Auto-Modus

Der Standardmodus auto arbeitet die WFS-Informationen in dieser Reihenfolge ab:

  1. GetCapabilities wird einmal geöffnet:

    root@kitploit:~
    /geoserver/wfs?service=WFS&acceptVersions=2.0.0&request=GetCapabilities
    
  2. Die XML-Antwort wird gestreamt. Sobald ein FeatureType/Name gefunden wird, steht der nächste typeName fest.

  3. Für diesen Layer wird unmittelbar DescribeFeatureType mit version=2.0.0 ausgeführt.

  4. Das Skript extrahiert die XSD-Elemente und wählt String-/JSON-Felder mit ID- oder Nummern-ähnlichem Namen aus.

  5. Der Kandidat wird abhängig vom Aufruf geprüft:

    • Ohne --sleep: Stichprobenwerte müssen syntaktisch gültiges JSON sein.
    • Mit --sleep N: Eine Kontrollanfrage und eine zeitbasierte Prüfanfrage werden gemessen. Die JSON-Wertprüfung wird dabei übersprungen.
  6. Das Ergebnis wird sofort ausgegeben und geflusht.

  7. Erst danach wird der nächste typeName aus der laufenden GetCapabilities-Antwort gelesen.

Dadurch muss eine große GetCapabilities-Antwort nicht vollständig verarbeitet werden, bevor das erste Ergebnis erscheint.

Kriterien für Feldkandidaten

Ohne --sleep berücksichtigt der automatische Modus standardmäßig String-/JSON-Felder mit ID- oder Nummern-ähnlichem Namen.

Mit --sleep verwendet --candidate-scope auto dagegen alle einfachen Nicht-Geometriefelder. XSD-Typ und ID-Namensmuster blockieren die Timing-Prüfung dann nicht mehr. Das verhindert False Negatives bei numerischen, Datum-/Boolean- oder herstellerspezifischen XSD-Typen.

Erkannte Namensmuster sind unter anderem:

root@kitploit:~
id
*_id
*_fid
nr_*
*_nr
*nummer*
fid
uuid
guid
key
objectid

Bei der zeitbasierten Prüfung muss der Feldname zusätzlich ein einfacher Bezeichner im Format [A-Za-z_][A-Za-z0-9_]* sein.

Unterschied zwischen JSON- und Sleep-Prüfung

Ohne --sleep wird geprüft, ob die beobachteten Werte syntaktisch als JSON interpretiert werden können. Deshalb gilt beispielsweise auch der String "383205" als Kandidat, weil sein Inhalt eine gültige JSON-Zahl darstellt. Diese Prüfung ist eine Heuristik und kein Schwachstellennachweis.

Mit --sleep 1 entscheidet ausschließlich die Zeitmessung. Ein Kandidat gilt standardmäßig als positiv, wenn die Prüfanfrage gegenüber der Kontrollanfrage mindestens 70 Prozent der angeforderten Sleep-Zeit zusätzlich benötigt. --timing-result-type auto prüft zuerst resultType=hits und bei einem negativen Ergebnis anschließend resultType=results.

Vorläufig positive Messungen werden zwingend mit einer längeren Sleep-Zeit bestätigt. Ohne explizites --confirm-sleep verwendet das Skript max(3, --sleep * 3), begrenzt auf 10 Sekunden. Dadurch führt eine einzelne Latenzspitze bei --sleep 1 nicht mehr zu vulnerable=true.

Kompakte Ausgabe

Die Standardausgabe enthält einen Block pro gültigem Layer:

root@kitploit:~
typeName=namespace:layer
field_name1=FIELD_A
parameter_string1=https://HOST/geoserver/wfs --typename namespace:layer --field_name FIELD_A
field_name2=FIELD_B
parameter_string2=https://HOST/geoserver/wfs --typename namespace:layer --field_name FIELD_B

parameter_stringN enthält den normalisierten WFS-Endpunkt und die passenden Werte für --typename und --field_name.

--valid-fields N zählt Layer-Blöcke, nicht einzelne Felder. Wenn weniger als N gültige Layer existieren, wird der restliche Katalog weiter untersucht. Mit --max-layers lässt sich die maximale Laufzeit begrenzen.

Ausführliche Diagnose

Die Optionen --diagnose oder --valid-diagnose FILE ergänzen unter anderem:

  • normalisierten WFS-Endpunkt,
  • verwendete GetCapabilities-URL,
  • DescribeFeatureType-URL,
  • XSD-Feldtypen,
  • ID- und Nutzbarkeitsmarkierungen,
  • Anzahl geprüfter Stichproben,
  • JSON-Kompatibilität oder Timing-Messwerte,
  • generierte GetFeature-URL und
  • kopierbare Parameterstrings.

Beispiel:

root@kitploit:~
python3 wfs_inventory.py \
  --url https://HOST \
  --valid-fields 10 \
  --valid-diagnose diagnose.txt

Weitere Inventurmodi

Alle Layer auflisten

root@kitploit:~
python3 wfs_inventory.py \
  --url https://HOST \
  --mode layers

Auf einen Namespace begrenzen:

root@kitploit:~
python3 wfs_inventory.py \
  --url https://HOST \
  --mode layers \
  --namespace fink

XSD-Felder eines Layers anzeigen

root@kitploit:~
python3 wfs_inventory.py \
  --url https://HOST \
  --mode fields \
  --layer namespace:layer

Jedes Feld wird als JSON-Objekt mit Name, XSD-Typ, nillable, id_candidate und usable_property ausgegeben.

Werte ausgewählter Felder exportieren

root@kitploit:~
python3 wfs_inventory.py \
  --url https://HOST \
  --mode values \
  --layer namespace:layer \
  --field FIELD_A \
  --field FIELD_B \
  --max-features 100 \
  --format jsonl \
  --output values.jsonl

Alle Properties exportieren:

root@kitploit:~
python3 wfs_inventory.py \
  --url https://HOST \
  --mode values \
  --layer namespace:layer \
  --all-properties \
  --max-features 100

Mit --unique werden identische Kombinationen ausgewählter Feldwerte nur einmal ausgegeben.

Parameter von wfs_inventory.py

ParameterStandardBedeutung
--url URLerforderlichHost, GeoServer-Basis oder vollständiger WFS-Endpunkt
--mode auto|layers|fields|valuesautoAuszuführender Betriebsmodus
--layer NAMESPACE:LAYER–Auto-Modus auf einen Feature-Type begrenzen; für fields und values erforderlich
--namespace PREFIX–Nur Layer dieses Namespace-Präfixes berücksichtigen
--capabilities-file FILE–Lokale GetCapabilities-Antwort statt eines Downloads verwenden
--field NAMEwiederholbarZu exportierendes Property im values-Modus
--all-propertiesausIm values-Modus alle Properties exportieren
--uniqueausDoppelte Feldwertkombinationen unterdrücken
--page-size N500Features pro GetFeature-Seite; Bereich 1 bis 5000
--sample-size N5Stichprobenwerte pro Layer für die JSON-Syntaxprüfung; Bereich 1 bis 100
--sleep SECONDS0Zeitbasierte Verifikation aktivieren; erlaubt sind 0 oder 1 bis 10 Sekunden
--candidate-scope auto|id|allautoKandidatenauswahl; auto nutzt ohne Sleep ID-Felder und mit Sleep alle Nicht-Geometriefelder
--timing-result-type auto|hits|resultsautoQuery-Pfad der Timing-Prüfung; auto probiert hits, danach results
--sleep-threshold RATIO0.7

Kombinierter Einstiegspunkt

geoserver_sqli_working.py kann die Inventurfunktion direkt aufrufen. Sobald --valid-fields angegeben ist, wird ausschließlich die Inventur ausgeführt und das Programm danach beendet.

Inventur über das kombinierte Skript

root@kitploit:~
python3 geoserver_sqli_working.py \
  --target https://HOST \
  --valid-fields 4 \
  --sleep 1 \
  --valid-diagnose output.txt

Dabei werden intern folgende Parameter an wfs_inventory.py weitergereicht:

root@kitploit:~
--target         -> --url
--valid-fields   -> --valid-fields
--valid-diagnose -> --valid-diagnose
--sleep          -> --sleep
--candidate-scope -> --candidate-scope
--timing-result-type -> --timing-result-type
--sleep-threshold -> --sleep-threshold
--confirm-sleep -> --confirm-sleep

Ohne explizites --sleep bleibt die zeitbasierte Prüfung im Inventurmodus deaktiviert.

Separater PoC-Modus

Nur für ausdrücklich autorisierte Testsysteme:

root@kitploit:~
python3 geoserver_sqli_working.py \
  --target https://HOST/geoserver/wfs \
  --typename namespace:layer \
  --field_name FIELD \
  --sleep 5

Im PoC-Modus wird der Zielpfad nicht automatisch normalisiert. Hier sollte der vollständige WFS-Endpunkt angegeben werden.

Der Modus führt zunächst einen Baseline-/Sleep-Test aus, testet anschließend die vorhandenen zeitbasierten Oracle-Varianten und liest bei erfolgreicher Bestätigung standardmäßig Server-/Datenbankmetadaten aus. Mit --query kann stattdessen eine eigene skalare Abfrage vorgegeben werden.

Der PoC-Modus deaktiviert derzeit die TLS-Zertifikatsprüfung intern. Für eine reine Inventur sollte bevorzugt wfs_inventory.py verwendet werden, da dort TLS standardmäßig geprüft wird.

Parameter von geoserver_sqli_working.py

ParameterStandardBedeutung
--target URLerforderlichZielhost oder WFS-Endpunkt; im PoC-Modus vollständigen WFS-Pfad verwenden
--typename NAMEfink_bku:fink_meta_mitte_suedwestFeature-Type für den PoC-Modus
--field_name NAMEerforderlich im PoC-ModusEinfacher XSD-Feldname für jsonArrayContains
--field-name NAMEAliasAlias für --field_name
--valid-fields N–Inventurmodus aktivieren und nach N gültigen Layern stoppen
--valid-diagnose FILE–Ausführlichen Inventurbericht in FILE schreiben; benötigt --valid-fields
--sleep SECONDSPoC: 5, Inventur: ausSleep-Dauer des jeweiligen Modus
--candidate-scope auto|id|allautoKandidatenauswahl im Inventurmodus
--timing-result-type auto|hits|resultsautoTiming-Query-Pfad im Inventurmodus
--sleep-threshold RATIO0.7Timing-Schwellwert im Inventurmodus
--confirm-sleep SECONDSautomatischBestätigungs-Sleep im Inventurmodus
--query SQL–Eigene skalare Abfrage im PoC-Modus
--debugausBedingungen, Laufzeiten und Entscheidungen im PoC-Modus anzeigen

JSONL-Bericht

Der Auto-Modus kann statt Textblöcken JSON Lines erzeugen:

root@kitploit:~
python3 wfs_inventory.py \
  --url https://HOST \
  --valid-fields 10 \
  --report-format jsonl \
  --output report.jsonl

Mit --diagnose enthält jeder Datensatz zusätzlich URLs, Kandidatenmetadaten, Prüfwerte und feldspezifische GetFeature-URLs.

Proxy und TLS

Proxy verwenden:

root@kitploit:~
python3 wfs_inventory.py \
  --url https://HOST \
  --proxy http://127.0.0.1:8080 \
  --valid-fields 4

Eigener Proxy-CA vertrauen:

root@kitploit:~
python3 wfs_inventory.py \
  --url https://HOST \
  --proxy http://127.0.0.1:8080 \
  --proxy-ca proxy-ca.pem \
  --valid-fields 4

TLS-Prüfung für ein autorisiertes Testsystem deaktivieren:

root@kitploit:~
python3 wfs_inventory.py \
  --url https://HOST \
  --insecure \
  --valid-fields 4

--proxy-ca und --insecure können nicht gemeinsam verwendet werden.

Große WFS-Kataloge und Performance

Bei großen GetCapabilities-Antworten helfen folgende Optionen:

root@kitploit:~
python3 wfs_inventory.py \
  --url https://HOST \
  --valid-fields 4 \
  --max-layers 100 \
  --sample-size 1 \
  --timeout 10 \
  --retries 0 \
  --delay 0

Hinweise:

  • GetCapabilities wird nur einmal angefordert und anschließend gestreamt.
  • --valid-fields 4 beendet den Scan erst nach vier gültigen Layern. Existieren weniger Treffer, läuft die Suche bis zum Ende oder bis --max-layers.
  • --sample-size 1 reduziert den Aufwand der JSON-Heuristik.
  • Im Sleep-Modus wird die JSON-Stichprobe übersprungen. Pro Query-Pfad erfolgen eine Kontroll- und eine Prüfanfrage. Bei --timing-result-type auto werden nach einem negativen hits-Ergebnis zusätzlich zwei results-Anfragen ausgeführt.
  • Ein vorläufig positiver Kandidat verursacht zwei weitere Anfragen für die skalierte Bestätigung. Erst danach gilt er als verwundbar.
  • --candidate-scope id reduziert die Zahl der Timing-Anfragen, kann aber verwundbare Felder mit anderen Namen auslassen.
  • --namespace und --start-layer-index können den Suchraum zusätzlich begrenzen.

Fehlerbehebung

The read operation timed out

  • --timeout erhöhen, wenn der Server langsam antwortet.
  • --retries 0 setzen, um lange Wiederholungen zu vermeiden.
  • --max-layers und --namespace verwenden.
  • Für die JSON-Heuristik --sample-size 1 verwenden.

Keine Ausgabe

  • Ohne --sleep müssen Kandidaten abhängig von --candidate-scope die XSD-/Namensprüfung und die JSON-Syntaxprüfung bestehen.
  • Mit --sleep werden nur zeitlich bestätigte Kandidaten als Parameterblock ausgegeben; negative Messungen erscheinen als [sleep-check] auf stderr.
  • Wenn weniger als die gewünschte Anzahl Treffer existiert, kann der Scan lange weiterlaufen. In diesem Fall --max-layers setzen.

Cannot do natural order without a primary key

Für die erste GetFeature-Seite sendet das Skript kein startIndex=0, da einige GeoServer-/JDBC-Layer ohne Primärschlüssel bereits dadurch eine natürliche Sortierung erzwingen. Beim Export weiterer Seiten kann ein solcher Layer trotzdem einen Primärschlüssel oder eine serverseitig unterstützte Sortierung benötigen.

schema does not define ...Type

Das Skript berücksichtigt sowohl den üblichen <LayerName>Type als auch einen abweichenden, im globalen XSD-Layerelement referenzierten oder anonymen complexType. Bleibt der Fehler bestehen, sollte die betreffende DescribeFeatureType-Antwort mit --diagnose geprüft werden.

HTTP 400 bei der Stichprobenprüfung

Die vollständige OWS-Fehlermeldung wird auf stderr ausgegeben. Häufige Ursachen sind nicht unterstützte Properties, serverseitige Paging-Vorgaben oder eine layerspezifische Datenquellenkonfiguration.

Hilfe direkt im Terminal

root@kitploit:~
python3 wfs_inventory.py --help
python3 geoserver_sqli_working.py --help
Tool herunterladen
Erforderlicher Anteil der Sleep-Zeit; Bereich 0.5 bis 1.0
--confirm-sleep SECONDS0/automatischBestätigungs-Sleep; 0 verwendet mindestens 3× die erste Sleep-Zeit, Bereich 1 bis 10
--start-layer-index N0Die ersten N gestreamten Layer überspringen
--max-layers N0Höchstens N Layer bearbeiten; 0 bedeutet unbegrenzt
--valid-fields N0Nach N gültigen Layer-Blöcken stoppen; 0 bedeutet unbegrenzt
--valid NAliasRückwärtskompatibler Alias für --valid-fields
--max-features N0Im values-Modus nach N Features stoppen; 0 bedeutet unbegrenzt
--format jsonl|csv|textjsonlAusgabeformat im values-Modus
--output FILEstdoutBericht oder Werte in eine Datei schreiben
--report-format blocks|jsonlblocksFormat des Auto-Berichts
--diagnoseausURLs, Typen, Auswahlflags und Prüfstatistiken ergänzen
--valid-diagnose FILE–Diagnose aktivieren und direkt in FILE schreiben
--delay SECONDS0.1Pause zwischen Ergebnis-/Prüfschritten
--timeout SECONDS30Timeout pro HTTP-Anfrage
--retries N2Wiederholungen nach Timeout oder Netzwerkfehler; Bereich 0 bis 10
--proxy URL–HTTP(S)-Proxy, beispielsweise http://127.0.0.1:8080
--proxy-ca FILE–PEM-CA-Zertifikat zum Vertrauen eines Proxy-Zertifikats
--insecureausTLS-Zertifikatsprüfung deaktivieren
--authorization TEXTI_AM_AUTHORIZEDSicherheitsbestätigung; muss exakt I_AM_AUTHORIZED sein