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安全漏洞