cURL库HTTP头部CRLF注入漏洞:请求走私与SSRF攻击的技术分析

本文详细分析了cURL/libcurl库的lib/http.c文件中`Curl_add_custom_headers`函数因缺少CRLF验证而导致的HTTP头部注入漏洞。该漏洞违反了RFC 7230协议规范,攻击者可利用其进行HTTP请求走私,并绕过安全边界实施服务器端请求伪造攻击,尤其在跟随重定向时风险显著。

HTTP请求走私与通过CRLF注入实现的SSRF

报告#3484431 - 在Curl_add_custom_headers中通过CRLF注入实现HTTP请求走私和SSRF

概述: 在lib/http.c:1761Curl_add_custom_headers函数中,由于缺乏CRLF(回车换行)验证,允许用户注入任意HTTP头部。这违反了RFC 7230 §3.2.4的规定,导致了HTTP请求走私和潜在的SSRF(服务器端请求伪造)绕过。 AI声明:我使用了AI助手来辅助进行初始的代码分析和补丁生成,但已通过十六进制转储和代理模拟手动验证了所有声明,以确保技术准确性。

受影响版本:

  • curl/libcurl 版本: 8.18.0-DEV 和 8.15.0
  • 平台: Linux (Kali Linux)
  • curl -V 输出: curl 8.18.0-DEV (x86_64-pc-linux-gnu) libcurl/8.18.0-DEV OpenSSL/3.5.4

复现步骤:

  1. 启动监听器捕获原始流量: nc -l -p 8080 > raw_http.txt
  2. 执行一个追加了包含CRLF自定义头部的libcurl应用程序(或curl CLI): curl -H "X-Injected: Value\r\nInjected-Header: Malicious" http://localhost:8080
  3. 检查捕获的输出: hexdump -C raw_http.txt
  4. 观察到CRLF字节(0d 0a)未经净化就被传输,导致接收方将注入的字符串解释为一个单独的、有效的HTTP头部。

支持材料/参考文献:

  • 十六进制转储证明: 十六进制转储显示在偏移量0x49处存在0d 0a,证实了协议层面的请求拆分。
  • 建议的补丁: 一个在lib/http.c中使用strchr来拒绝\r\n的验证补丁成功地缓解了此问题。

影响: libcurl头部处理中缺乏CRLF验证允许进行HTTP请求走私,使得攻击者能够绕过安全边界并执行服务器端请求伪造。由于libcurl是一个被无数应用程序和后端使用的基础库,此漏洞构成了系统性风险。具体来说,注入的头部在重定向(-L)过程中会持续存在,这显著增加了攻击面,并可能导致孤立的内部服务暴露或缓存中毒。

时间线:

  • n12d11n 向curl提交报告。 9天前
  • jimfuller2024 curl 员工 发表评论。 9天前

感谢报告,正在调查。

  • jimfuller2024 curl 员工 发表评论。 9天前

我们遇到过很多这个主题的变体——如果有人可以运行curl,就没有什么能阻止他们直接添加每个头部(例如,不需要走私)……调用curl或libcurl的应用程序应该进行净化。

  • n12d11n 发表评论。 9天前

感谢您的反馈。我理解关于调用libcurl的应用程序应该对其输入进行净化的观点。但是,我想提出两点技术性建议供重新考虑:

  1. 协议完整性 (RFC 7230 §3.2.4): 根据RFC,字段值不得包含CR或LF。通过允许这些字符,libcurl正在生成格式错误的HTTP消息。作为一个基础协议库,libcurl应该强制执行其实现协议的基本语法,以确保互操作性和安全性。
  2. 请求走私与自定义头部: 虽然用户可以合法地添加任何头部,但这里的问题是请求注入。攻击者向一个易受攻击的应用程序(使用libcurl作为后端)提供输入时,可以将一个全新的、第二个HTTP请求注入到同一个TCP流中。这绕过了应用程序预期的逻辑,这是CWE-444(HTTP请求走私)的核心。
  3. 代理歧义性: 我们的PoC证明,当libcurl位于代理之后时,这种CRLF注入会导致代理将流解释为两个独立的请求。这可以被滥用以执行SSRF或缓存中毒,即使应用程序严格控制其访问的URL。

我们认为,在库级别对CRLF进行净化为复杂的网络基础设施提供了关键的“深度防御”,防止libcurl被用作走私工具。

  • bagder curl 员工 发表评论。 9天前

请随时在邮件列表或GitHub上讨论这个问题。缺乏crlf过滤是有文档说明和警告的,因此不被视为漏洞。

  • n12d11n 发表评论。 9天前

感谢您的澄清。我理解这种行为是有文档记录的。但是,我想将我的发现作为安全加固建议提交,而不仅仅是错误报告。

虽然净化的责任目前在于应用程序开发者,但我们的调查显示:

  • 隐含信任: 许多开发者假设像libcurl这样的高级别、生产级库会自动执行RFC 7230协议语法。
  • 重定向中的SSRF风险: 最关键的部分是注入的头部在重定向过程中持续存在。一个应用程序可能会净化其初始输入,但如果恶意头部被注入到初始请求中,它可能在30x重定向过程中被携带到内部或敏感主机。

我已经准备了一个最小的补丁,在lib/http.c中使用strchr实现了严格的CRLF过滤。它有效地防止了请求走私,并且对合法头部性能零影响。

即使这不符合赏金条件,我也很乐意将这个讨论移到GitHub或邮件列表,以为项目贡献这个补丁。您建议我为此加固措施提交一个拉取请求吗?

  • bagder curl 员工 关闭报告并将状态更改为“不适用”。 9天前

感谢您的报告。

欢迎并鼓励您帮助我们改进libcurl。但此类讨论和改进需要在公共论坛上进行,而不是在这里。

此问题不被视为安全问题,我正试图通过这个PR更清楚地说明这一点: https://github.com/curl/curl/pull/20157

  • bagder curl 员工 请求披露此报告。 9天前

根据项目透明度政策,我们希望所有报告都被披露并公开。

  • n12d11n 发表评论。 9天前

感谢您的澄清,Daniel。我理解项目关于已记录行为以及调用应用程序责任的策略。我很高兴看到这份报告通过链接的PR有助于使文档更加清晰。我同意请求披露,以帮助其他开发者理解在使用这些API时输入净化的重要性。致以诚挚的问候。

  • bagder curl 员工 披露此报告。 9天前

报告详情:

项目 信息
报告时间 2026年1月2日 1:51 AM UTC
报告人 n12d11n
报告对象 curl
报告 ID #3484431
严重性 高 (7 ~ 8.9)
披露时间 2026年1月2日 10:50 AM UTC
漏洞类型 HTTP 请求走私
CVE ID
赏金
账户详情

看起来您的JavaScript被禁用了。要使用HackerOne,请在浏览器中启用JavaScript并刷新此页面。

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