curl URL解析不一致性导致SSRF与访问控制绕过风险分析

本文详细分析了curl在解析含IPv6区域标识符的URL时存在的不一致性问题,该问题可能导致服务器端请求伪造和访问控制绕过等安全风险,并探讨了与RFC 6874标准的合规性争议。

0x01 摘要

curl的URL处理中存在URL解析不一致性问题,可能导致服务器端请求伪造(SSRF)和访问控制绕过等安全风险。具体而言,当解析包含IPv6地址和区域标识符的URL时,curl解析器会省略区域标识符,这与RFC 6874规定的预期行为不符。这种不一致性可能导致依赖curl进行URL验证和解析的应用程序错误解读网络接口,从而引发安全漏洞。

0x02 详细信息

2.1 受影响组件

  • curl:截至报告时的所有版本
  • libcurl:截至报告时的所有版本

2.2 技术背景

根据RFC 6874,在URI中包含IPv6区域标识符时,区域标识符必须进行百分号编码并包含在IPv6地址字面量的方括号内。

RFC 6874第4节规定: “本文档规定区域标识符应跟在百分号后附加到地址字面量。在URI中百分号需要进行URL转义,这样区域标识符就能正确识别为地址字面量的一部分,而不是端口或用户信息组件。”

2.3 不一致的解析行为

下表展示了不同库解析包含IPv6地址和区域标识符的URL时的结果:

Payload Browser (Chrome) Rust libcurl Go net/url Python urllib Python urllib3
http://[fe80::1%25eth0]/ Invalid URL Invalid IPv6 address [fe80::1] fe80::1%eth0 fe80::1%eth0 [fe80::1%eth0]
http://[fe80::1%251]/ Invalid URL Invalid IPv6 address [fe80::1] fe80::1%1 fe80::1%1 [fe80::1%1]
http://[fe80::1]/ [fe80::1] [fe80::1] [fe80::1] fe80::1 fe80::1 [fe80::1]

观察发现:libcurl从主机名中剥离了区域标识符%eth0,结果为[fe80::1]。相比之下,Go的net/url和Python的urllib保留了区域标识符为fe80::1%eth0。

2.4 问题解释

  • 偏离RFC 6874:区域标识符对于IPv6链路本地地址指定网络接口至关重要。省略它可能导致不正确的网络路由或意外接口使用。
  • 不一致解析:curl省略区域标识符意味着使用libcurl的应用程序可能无意中连接到错误的接口或完全无法连接。
  • 安全影响:此行为可能被利用来绕过网络限制,导致SSRF攻击或对资源的未授权访问。

0x03 攻击场景

3.1 SSRF场景

  • 应用程序设置:Web应用程序使用libcurl从用户提供的URL获取资源。它依赖libcurl进行URL解析,并相信对链路本地地址的请求被限制在特定接口。
  • 攻击者输入:攻击者提交类似http://[fe80::1%25eth0]/的URL。
  • 解析行为
    • 预期:应用程序期望主机名为fe80::1%eth0,确保请求通过eth0接口。
    • 实际:libcurl将主机名解析为fe80::1,忽略%eth0区域标识符。
  • 利用:请求被发送到默认网络接口的fe80::1,而不是预期的eth0。攻击者可以操纵区域标识符强制请求通过意外接口,可能访问受限网络或服务。

3.2 访问控制绕过

  • 防火墙规则:应用程序有仅允许通过特定接口(由区域标识符识别)流量的防火墙规则。
  • 绕过控制:通过利用解析不一致性,攻击者可以省略区域标识符,导致请求绕过应用程序逻辑强制实施的接口限制。

0x04 影响

  • 服务器端请求伪造:攻击者可操纵请求访问内部资源。
  • 访问控制绕过:可规避基于网络接口的安全策略。
  • 信息泄露:如果内部服务被访问,可能导致敏感数据暴露。

0x05 缓解措施

  • 更新解析逻辑:修改libcurl严格遵循RFC 6874,确保正确解析和保留区域标识符。
  • 输入验证:应用程序应实施额外检查以验证区域标识符存在且格式正确。
  • 升级:鼓励用户在修复版本发布后更新到修补的curl版本。

0x06 参考文献

  • RFC 6874:在地址字面量和统一资源标识符中表示IPv6区域标识符
  • CWE-939:URL编码语法处理不当
  • CWE-918:服务器端请求伪造

时间线与讨论

2024年10月31日13:57 UTC - z3r0yu向curl提交报告

2024年10月31日14:09 UTC - bagder确认收到报告并开始调查

2024年10月31日14:51 UTC - bagder询问问题是否在于区域标识符未在连接时使用

2024年10月31日18:45 UTC - dfandrich提到CURLU API可解决此问题

2024年11月1日01:41 UTC - z3r0yu澄清问题涉及解析和连接两个层面

2024年11月1日03:35 UTC - dfandrich要求提供可复现的测试代码

2024年11月1日08:42 UTC - bagder指出curl 7.68.0版本过旧,且区域标识符是独立组件

2024年11月2日09:28 UTC - bagder关闭报告,状态设为"不适用",认为curl按设计和文档正常工作

报告披露 - 根据项目透明政策,报告被公开披露

技术讨论要点

  • 争议焦点在于区域标识符是否应被视为主机名的一部分
  • curl团队认为区域标识符是独立组件,此设计决策已存在5年以上
  • 使用CURLU API可正确解析区域标识符,但连接逻辑是否使用存在争议
  • 最终认定URL解析差异是预期行为,不构成curl安全漏洞
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计