DNS重绑定攻击漏洞报告
漏洞概述
在SSRF过滤器中存在DNS重绑定漏洞。该库验证主机名的IP地址,但随后将主机名传递给Net::HTTP.start(),后者会执行自己的DNS查询。攻击者可以控制一个DNS服务器,在验证期间返回安全的公共IP,然后在Net::HTTP稍后解析时返回127.0.0.1。
技术细节
漏洞代码
|
|
攻击示例
攻击者设置evil.com的DNS以交替响应:
- 第一次查询(验证期间)返回8.8.8.8
- 第二次查询(Net::HTTP内部查找)返回127.0.0.1
结果:SsrfFilter.get('http://evil.com:6379')绕过所有保护并命中本地主机上的某些内部服务。
修复建议
推荐修复方案
直接连接到验证过的IP而不是主机名:
- 将
Net::HTTP.start(uri.hostname, ...)改为Net::HTTP.start(validated_ip, ...) - 手动设置Host头:
headers['Host'] = uri.hostname - 使用
ssl_hostname: uri.hostname进行正确的TLS证书验证
版本分析
v1.1.2(安全)
安全原因是第178行的代码:
|
|
这行代码在将URI对象传递给Net::HTTP之前修改了它,因此即使代码显示Net::HTTP.start(uri.hostname, ...),它实际上使用的是IP地址。
v1.3.0(回归错误)
当PR #73添加ipaddr:选项时,它同时移除了uri.hostname = ip行。现在Net::HTTP直接接收主机名,这允许DNS重绑定。
技术验证
ipaddr选项测试
|
|
跨版本测试结果
- Ruby 2.6.10:完全忽略ipaddr参数
- Ruby 3.3.0:ipaddr参数正常工作并防止DNS解析
防御建议
建议采用深度防御方法,在保留ipaddr参数的同时恢复v1.1.2中的uri.hostname = ip行。这将提供两个独立的保护层:
- 即使Ruby的ipaddr实现存在错误
- 或者有人使用不同的HTTP客户端
主机名替换仍然可以防止DNS重绑定。这是一个最小的代码变更,能显著增强安全态势。
影响评估
该漏洞允许攻击者通过DNS重绑定技术绕过SSRF保护,访问内部服务,安全风险等级为严重(10.0)。