惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
H
Help Net Security
云风的 BLOG
云风的 BLOG
Apple Machine Learning Research
Apple Machine Learning Research
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Hugging Face - Blog
Hugging Face - Blog
博客园_首页
D
Docker
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Blog — PlanetScale
Blog — PlanetScale
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
GbyAI
GbyAI
博客园 - Franky
B
Blog RSS Feed
Stack Overflow Blog
Stack Overflow Blog
L
LangChain Blog
量子位
V
Visual Studio Blog
Y
Y Combinator Blog
小众软件
小众软件
N
Netflix TechBlog - Medium
博客园 - 三生石上(FineUI控件)
Microsoft Security Blog
Microsoft Security Blog
雷峰网
雷峰网

FreeBuf网络安全行业门户

Anthropic 强化 Claude 安全防护:AI 模型在评估中未经授权访问真实系统 黑名单只防了 AWS?Directus 默认配置下 SSRF 直通国产云 metadata 告警堆到 100 万条那天,我决定自己写一个“会用 AI“的安全运营中心 - FreeBuf网络安全行业门户 新手勇闯网络安全 | 网络通信基础(三) - FreeBuf网络安全行业门户 FreeBuf早报 | 宇树G1 EDU人形机器人漏洞可致root级远程代码执行;Claude平台遭攻击 - FreeBuf网络安全行业门户 保障 Claude Code 安全:全新 Compliance API、本地可见性与身份治理 Apache Shiro rememberMe 反序列化漏洞:从 Cookie 到 RCE 免费路由器 DNS 调整可拦截家庭网络中的恶意软件和钓鱼攻击 - FreeBuf网络安全行业门户 黑客利用信息窃取恶意软件窃取 Claude 登录会话,劫持账户 - FreeBuf网络安全行业门户 奇安信2026半年报:营收跌了14%,亏损却砍半,这笔账怎么算? - FreeBuf网络安全行业门户 出厂即后门:一台深圳路由器里藏着的两个钉子户——SPEAKINGSTONE 与 DARKLANTERN 拆解 - FreeBuf网络安全行业门户 让 root 替你写文件:cPanel 域停放附加域提权拆解(CVE-2026-65643) - FreeBuf网络安全行业门户 量化公司策略代码全生命周期安全平台建设方案 - FreeBuf网络安全行业门户 AI Agent 工具调用的信任边界:从 MCP 攻击面到"Agent 信任链"模型 新手勇闯网络安全 | 网络通信基础(二) - FreeBuf网络安全行业门户 HW 蓝队·异常外联流量溯源实战:那些告警背后真正在发生什么 - FreeBuf网络安全行业门户 Apache Tomcat CVE-2026-65182 分析:一次 SecurityConstraint 最长匹配逻辑缺陷导致的访问控制绕过 安全度量:拿什么向管理层证明安全的价值 - FreeBuf网络安全行业门户 曼彻斯特机场集团确认客户数据遭窃取 - FreeBuf网络安全行业门户 黑客利用 Claude 和 ChatGPT 入侵多个政府机构 报告:思科或以超2.5亿美元收购AI Agent安全初创公司Astrix Security 【安全圈】国家网络安全通报中心:近期集中爆发多起供应链投毒攻击事件 员工自费买Token引爆内网?揭秘AI中转站的四种“投毒”手段与供应链危机 AI 路由漏洞可被利用注入恶意代码并窃取敏感数据 黑客滥用 GitHub 和 GitLab 托管恶意软件并实施凭证钓鱼攻击 Claude 在数分钟内发现存在 13 年的 ActiveMQ 远程代码执行漏洞 2026攻防演练红队高频面试题30个(含答案)! AI Agent沙箱之ANOLISA内置沙箱 XXE 漏洞原理剖析:DTD、实体解析机制与攻击链构建 谷歌预警引发连锁反应:Cloudflare正积极调整抗量子加密战略优先级
一个 STOR 文件名,让 PostgreSQL 替你执行命令——ProFTPD mod...
关 注 0 文章数 0 关注者 · 2026-08-29 · via FreeBuf网络安全行业门户

freeBuf

主站

分类

云安全 AI安全 开发安全 终端安全 数据安全 Web安全 基础安全 企业安全 关基安全 移动安全 系统安全 其他安全

特色

热点 工具 漏洞 人物志 活动 安全招聘 攻防演练 政策法规

前言

FTP 还能注入 SQL?说实话,看到这个 CVE 的第一眼,我脑子里浮现的是 2008 年的 PHP 教程:把表单里的字符串拼进 SQL 查询,然后被管理员骂一顿。

但这次的注入点不在表单,在 FTP 的文件名里;被注入的不是网站数据库,是 ProFTPD 的访问日志系统;而攻击的终点,是 PostgreSQL 的COPY ... TO PROGRAM——一条能让数据库替攻击者执行操作系统命令的语句。

8 月 25 日,exploit 公开,编号 CVE-2026-42167。攻击者只需要一个合法的 FTP 账号(认证后利用),就能在服务器上执行任意命令。

老协议,新玩法。拆开看看。

一、mod_sql:一个用 SQL 记日志的模块

ProFTPD 是 Linux 世界最常见的 FTP 服务器之一,mod_sql 是它的一个扩展模块,干一件事:把 FTP 服务器的行为记到 SQL 数据库里——谁登录了、上传了什么、下载了什么。

记录的形式很灵活,管理员可以在 proftpd.conf 里定义"命名查询"(SQLNamedQuery),把日志事件映射成 SQL 语句。比如常见的配置:

SQLNamedQuery uploaded UPDATE lastlog SET last=now(), file='%f' WHERE user='%u'

这里%f会被替换成上传的文件名,%u替换成用户名——ProFTPD 的日志模板变量。写完这个映射,用户在 FTP 上做的每个动作,都会被翻译成一条 SQL 语句执行。

问题来了:如果文件名本身不是"文件名",而是精心构造的 SQL 片段呢?

mod_sql 的设计者不是没想过这个问题——他们想了,还写了专门的转义逻辑,只是这个逻辑本身被绕过了。

二、漏洞的钥匙:is_escaped_text 的"好心"

先看转义逻辑。mod_sql 里有个函数叫is_escaped_text,作用是判断一段文本"是否已经被 SQL 转义过了":

static int is_escaped_text(const char *text, size_t text_len) {
  register unsigned int i;

  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;
}

逻辑简单粗暴:首字符是单引号、末字符是单引号、中间没有其他单引号——那就判定"这段文本已经是转义过的",直接放行。

这个判断是为谁设计的?为了兼容:有些 SQL 查询里管理员自己已经写了带引号的字面量(比如WHERE user='admin'),如果模块再转义一遍,引号会变成\',SQL 就错了。所以模块做了这个启发式判断,避免"双重转义"。

它被调用的地方在sql_resolved_append_text()里:

if (is_escaped_text(text, text_len) == FALSE) {
  mr = sql_dispatch(sql_make_cmd(p, 2, resolved->conn_name, text),
    "sql_escapestring");
  if (check_response(mr, resolved->conn_flags) < 0) {
    errno = EIO;
    return -1;
  }
  new_text = (char *) mr->data;
  new_textlen = strlen(new_text);
} else {
  pr_trace_msg(trace_channel, 17,
    "text '%s' is already escaped, skipping escaping it again", text);
}

翻译成人话:只要文本首尾是单引号、中间没有单引号,模块就信任它,原样拼进 SQL 语句,跳过转义。

这个"信任"就是整条漏洞链的起点。

一个启发式判断撑不起安全边界——"看起来像转义过的"和"确实是转义过的",是两个概念。

三、源码走读:文件名是怎么变成 SQL 的

把完整链路走一遍,你会看到文件名从"数据"变成"代码"的全过程。

第一步,拼 SQL 语句。在process_named_query()里,命名查询被拼装成最终 SQL:

if (strcasecmp(c->argv[0], SQL_INSERT_C) == 0) {
  query = pstrcat(cmd->tmp_pool, "INTO "

已在FreeBuf发表 0 篇文章

本文为 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)