0x01 摘要
curl的URL处理中存在URL解析不一致性问题,可能导致服务器端请求伪造(SSRF)和访问控制绕过等安全风险。具体来说,当解析包含IPv6地址和区域标识符的URL时(例如http://[fe80::1%25eth0]/),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 | 浏览器 (Chrome) | Rust | libcurl | Go net/url | Python urllib | Python urllib3 |
|---|---|---|---|---|---|---|
http://[fe80::1%25eth0]/ |
无效URL | 无效IPv6地址 | [fe80::1] |
fe80::1%eth0 |
fe80::1%eth0 |
[fe80::1%eth0] |
http://[fe80::1%251]/ |
无效URL | 无效IPv6地址 | [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 影响
- 服务器端请求伪造(SSRF):攻击者可以操纵请求以访问内部资源。
- 访问控制绕过:可以规避基于网络接口的安全策略。
- 信息泄露:如果访问内部服务,可能暴露敏感数据。
0x05 缓解措施
- 更新解析逻辑:修改libcurl以严格遵循RFC 6874,确保正确解析和保留区域标识符。
- 输入验证:应用程序应实施额外检查以验证区域标识符是否存在且格式正确。
- 升级:鼓励用户在修复版本发布后更新到curl的修补版本。
0x06 参考资料
- RFC 6874:在地址字面量和统一资源标识符中表示IPv6区域标识符
- CWE-939:URL编码语法处理不当
- CWE-918:服务器端请求伪造(SSRF)
时间线讨论
2024年10月31日,下午1:57(UTC) z3r0yu向curl提交报告
2024年10月31日,下午2:09(UTC) bagder(curl工作人员)发表评论: “感谢您的报告!我们将花时间调查您的报告,并尽快向您提供详细信息和可能的后续问题!很可能在接下来的24小时内。我们始终努力尽快修复报告的问题。严重性为低或中等的问题我们会合并到普通发布周期中的下一个版本。只有更严重的问题我们可能会提前发布修复。”
2024年10月31日,下午2:51(UTC) bagder发表评论: “这份报告让我感到困惑,它谈论解析器中的问题,但实际上似乎说问题是指定的区域ID在连接到IPv6地址时实际上没有被使用。我说得对吗?”
2024年10月31日,下午2:59(UTC) bagder发表评论: “如果我们假设是这种情况,您如何确定区域ID没有被使用?”
2024年10月31日,下午3:38(UTC) bagder更新评论: “允许用户提供的URL,然后尝试使用允许列表/阻止列表过滤这些URL注定会失败,不能被视为curl安全问题。这是因为URL notoriously 糟糕/未标准化,没有两个URL解析器会以相同方式处理所有URL。应用程序应预期实现之间的URL处理差异。”
2024年10月31日,下午6:45(UTC) dfandrich(curl工作人员)发表评论: “这是创建CURLU API的一个重要动机。如果应用程序按预期使用它来解析URL,那么这个问题就会消失。参见https://daniel.haxx.se/blog/2022/01/10/dont-mix-url-parsers/”
2024年11月1日,上午1:41(UTC) z3r0yu发表评论: “亲爱的Daniel和curl团队,感谢您花时间审查我的报告。我感谢您的反馈,并希望澄清问题并回答您的问题…”
(后续讨论主要围绕技术细节、测试方法和对RFC标准的解释展开,最终curl团队认为这不是安全问题,报告状态被标记为"不适用")
2024年11月2日,上午9:28(UTC) bagder关闭报告并将状态更改为"不适用": “如上所述,此问题不被认为是curl安全漏洞。curl按预期和文档记录的方式工作。”
5天前 bagder请求披露此报告: “根据项目透明政策,我们希望所有报告都被披露并公开。”
5天前 bagder披露了此报告。