在这篇文章:谈一谈如何在 Python 开发中拒绝 SSRF 漏洞 里面提出:
这种处理流程真的能避免 SSRF 吗?
可以避免的有:
......
看起来似乎很完美,但是还有一种攻击可以绕过此种处理流程,就是 DNS Rebinding Attack。
攻击原理:
一般进行 ssrf 防御的模式如下:
观察到,在这个流程中,一共进行了两次DNS解析:第一次是对URL的host进行DNS解析,第二次是使用CURL发包的时候进行解析。这两次DNS解析是有时间差的,我们可以使用这个时间差进行绕过。
事件差对应的DNS中的机制是TTL
。TTL表示DNS里面域名和IP绑定关系的Cache在DNS上存活的最长时间。即请求了域名与iP的关系后,请求方会缓存这个关系,缓存保持的时间就是TTL。而缓存失效后就会删除,这时候如果重新访问域名指定的IP的话会重新建立匹配关系及cache。
在上面的流程中,如果在DNS第二次解析的时候,我们能够更换URL对应的IP,那么在TTL之后、缓存失效之后,重新访问此URL的话,就能获取被更换后的IP。如果我们把第一次解析的IP设为合法IP,就能绕过host合法性检查了;把第二次解析的IP设为内网IP,就达到了SSRF访问内网的目的。
在这个过程中,对于浏览器来说,整个过程访问的都是同一域名,所以认为是安全的。这就会导致绕过。
所以总结一下:
DNS 重绑定攻击的原理是:利用服务器两次解析同一域名的短暂间隙,更换域名背后的ip达到突破同源策略或过waf进行ssrf的目的。
时间窗口问题:
TTL 最理想的设置是0,即在第一次解析之后,立马换位我们想要访问的内网IP。
但是现实