libcurl FTP路径规范化漏洞解析:编码路径遍历风险与修复方案

本文详细分析libcurl在处理FTP路径时存在的安全漏洞,攻击者可通过编码的%2e%2e实现目录遍历,导致敏感文件泄露。文章包含漏洞原理、复现步骤、影响分析和修复建议,适用于安全研究人员和开发人员参考。

libcurl FTP路径规范化漏洞分析报告

漏洞概述

报告ID: #3418861
漏洞类型: 路径遍历 (CWE-22)
提交者: ahn0x
提交时间: 2天前
状态: 已关闭(不适用)

技术细节

漏洞原理

libcurlftp_parse_url_path函数(位于lib/ftp.c)在处理FTP路径时存在安全缺陷:

  1. URL解码阶段:函数首先对FTP路径段进行URL解码(如将%2e%2e解码为..
  2. 路径分割阶段:使用特设循环将解码后的路径分割为组件,跳过由//产生的空组件
  3. 缺失规范化:代码未执行规范的路径规范化(无基于堆栈的...处理)

攻击向量

编码的遍历序列如%2e%2e被解码为..后,可能成为正常路径组件,导致libcurl向远程FTP服务器发出CWD ..命令。在攻击者能够向使用libcurl的应用程序提供FTP URL的情况下,这实现了客户端驱动的目录遍历。

受影响版本

测试环境:

  • curl 8.4.0 (x86_64-pc-linux-gnu)
  • libcurl/8.4.0
  • OpenSSL/1.1.1k
  • zlib/1.2.11

注意:该问题在curl 8.13.0及以后版本中已修复。

复现步骤

环境准备

1
2
3
4
mkdir -p ~/curl-test/dir ~/curl-test/testdir
echo "INSIDE" > ~/curl-test/dir/inside.txt
echo "OUTSIDE" > ~/curl-test/testdir/outside.txt
cd ~/curl-test

启动FTP服务器

1
2
python3 -m pip install pyftpdlib
python3 -m pyftpdlib -w

执行攻击

1
curl --trace-ascii curl_trace.txt -v "ftp://127.0.0.1:2121/dir//%2e%2e/testdir" 2>&1 | tee curl_stdout.txt

跟踪输出示例

1
2
3
4
CWD dir
< 250 "/dir" is the current directory.
CWD ..
< 250 "/" is the current directory.

影响分析

安全风险

  • 路径遍历 (CWE-22) - 输入验证不当 (CWE-20)

实际攻击场景

  1. 远程文件泄露(机密性):攻击者可构造导致libcurl遍历到父目录并尝试在目标目录外进行RETR的URL
  2. 客户端过滤器绕过(完整性/授权):执行简单清理(如搜索字面..)的应用程序可能被编码等效项(%2e%2e)绕过
  3. 供应链和自动化滥用:自动处理FTP URL的软件可能被诱骗获取或覆盖允许区域外的文件

可利用性前提

  • 攻击者必须能够提供由使用libcurl的应用程序处理的FTP URL
  • 核心逻辑中无需特殊身份验证

严重程度

建议严重性:高
CVSS向量示例:AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:N → CVSS ~7.x

相关代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
/* URL解码FTP路径以便进一步评估 */
result = Curl_urldecode(ftp->path, 0, &ftpc->rawpath, &pathLen, REJECT_CTRL);

/* 将URL路径解析为单独的路径组件 */
while(dirAlloc--) {
    const char *spos = strchr(curPos, '/');
    size_t clen = spos - curPos;
    if(!clen && (ftpc->dirdepth == 0))
        ++clen;
    /* 我们跳过空的路径组件,如"x//y"... */
    if(clen) {
        ftpc->dirs[ftpc->dirdepth].start = (int)(curPos - rawPath);
        ftpc->dirs[ftpc->dirdepth].len = (int)clen;
        ftpc->dirdepth++;
    }
    curPos = spos + 1;
}

/* 接收器:稍后用于发送CWD */
result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s", ftpc->entrypath);

修复建议

  1. 执行规范路径规范化:在URL解码之后、分割路径组件之前执行基于堆栈的./..处理,压缩//
  2. 拒绝遍历尝试:对于尝试遍历到允许根目录之上的路径返回错误,而不是发送CWD
  3. 添加单元测试:为编码的遍历情况和混合排列添加单元测试

项目方回应

bagder (curl工作人员) 评论:

  • 该问题在curl 8.13.0或更高版本中不存在
  • 允许攻击者控制URL本身就是一场必输的战斗
  • FTP客户端完全可以按要求更改目录到"..",适当的目录保护必须在服务器端实现
  • 不能依赖客户端保护

报告状态

  • 关闭原因:不适用(不被视为安全问题)
  • 披露状态:已披露(遵循项目透明度政策)
  • 赏金:无

AI使用声明

报告提交者声明:使用AI助手帮助起草和构建此报告,所有技术声明、测试和跟踪摘录都在本地测试环境中手动执行和验证,未使用AI生成利用代码。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计