Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
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.

View Repository
1191 month agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

GeoServer WFS Inventory and Authorized Verification

This repository contains two Python scripts for investigating GeoServer WFS endpoints.

Overview

wfs_inventory.py

Purpose: Inventory layers, XSD fields, and WFS values, and optionally verify candidates via a time-based check.

Execution examples:

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

geoserver_sqli_working.py

Purpose: Combined entry point for inventory as well as a separate PoC mode.

Execution examples:

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

Important note: The time-based check and the PoC mode may only be used against systems for which explicit testing authorization has been granted. The normal inventory mode uses exclusively regular WFS operations.

Prerequisites

  • Python 3.10 or newer
  • No additional Python packages; both scripts use only the standard library
  • Network access to the WFS endpoint

Optionally make executable:

chmod +x wfs_inventory.py geoserver_sqli_working.py

Quick Start

Search for candidates via regular WFS queries

python3 wfs_inventory.py \
  --url https://HOST \
  --valid-fields 4

The default path /geoserver/wfs is appended automatically. The following specifications are therefore equivalent:

https://HOST
https://HOST/geoserver
https://HOST/geoserver/wfs

For a non-standard installation, the full WFS path must be specified.

Verify candidates with a time-based check

Only for explicitly authorized systems:

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

During the check, a measurement per candidate appears on stderr:

[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

A passed screen is not yet a positive finding. Only when the second, longer measurement also passes is a parameter block output.

Write diagnostics to a file

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

--valid-diagnose FILE automatically enables verbose diagnostics and writes them to the specified file.

Auto Mode Flow

The default auto mode processes the WFS information in this order:

  1. GetCapabilities is opened once:

    /geoserver/wfs?service=WFS&acceptVersions=2.0.0&request=GetCapabilities
    
  2. The XML response is streamed. As soon as a FeatureType/Name is found, the next typeName is determined.

  3. For this layer, DescribeFeatureType is immediately executed with version=2.0.0.

  4. The script extracts the XSD elements and selects string/JSON fields with ID- or number-like names.

  5. The candidate is checked depending on the invocation:

    • Without --sleep: Sample values must be syntactically valid JSON.
    • With --sleep N: A control request and a time-based test request are measured. The JSON value check is skipped in this case.
  6. The result is output immediately and flushed.

  7. Only then is the next typeName read from the ongoing GetCapabilities response.

This means a large GetCapabilities response does not need to be fully processed before the first result appears.

Criteria for field candidates

Without --sleep, the automatic mode by default considers string/JSON fields with ID- or number-like names.

With --sleep, --candidate-scope auto instead uses all simple non-geometry fields. XSD type and ID name patterns no longer block the timing check. This prevents false negatives for numeric, date/boolean, or vendor-specific XSD types.

Recognized name patterns include, among others:

id
*_id
*_fid
nr_*
*_nr
*nummer*
fid
uuid
guid
key
objectid

For the time-based check, the field name must additionally be a simple identifier in the format [A-Za-z_][A-Za-z0-9_]*.

Difference between JSON and sleep check

Without --sleep, it is checked whether the observed values can be syntactically interpreted as JSON. Therefore, for example, the string "383205" also counts as a candidate because its content represents a valid JSON number. This check is a heuristic and not proof of vulnerability.

With --sleep 1, only the time measurement decides. A candidate is considered positive by default if the test request takes at least 70 percent of the requested sleep time in addition to the control request. --timing-result-type auto first checks resultType=hits and, in the event of a negative result, subsequently resultType=results.

Provisionally positive measurements are mandatorily confirmed with a longer sleep time. Without an explicit --confirm-sleep, the script uses max(3, --sleep * 3), capped at 10 seconds. This means a single latency spike with --sleep 1 no longer leads to vulnerable=true.

Compact Output

The standard output contains one block per valid layer:

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 contains the normalized WFS endpoint and the matching values for --typename and --field_name.

--valid-fields N counts layer blocks, not individual fields. If fewer than N valid layers exist, the remaining catalog continues to be examined. --max-layers can be used to limit the maximum runtime.

Verbose Diagnostics

The options --diagnose or --valid-diagnose FILE additionally include:

  • normalized WFS endpoint,
  • used GetCapabilities URL,
  • DescribeFeatureType URL,
  • XSD field types,
  • ID and usability flags,
  • number of samples checked,
  • JSON compatibility or timing measurements,
  • generated GetFeature URL and
  • copyable parameter strings.

Example:

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

Additional Inventory Modes

List all layers

python3 wfs_inventory.py \
  --url https://HOST \
  --mode layers

Restrict to a namespace:

python3 wfs_inventory.py \
  --url https://HOST \
  --mode layers \
  --namespace fink

Display XSD fields of a layer

python3 wfs_inventory.py \
  --url https://HOST \
  --mode fields \
  --layer namespace:layer

Each field is output as a JSON object with name, XSD type, nillable, id_candidate, and usable_property.

Export values of selected fields

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

Export all properties:

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

With --unique, identical combinations of selected field values are output only once.

Parameters of wfs_inventory.py

Download Tool