主页 > 网络知识 > SSRF安全指北(3)

SSRF安全指北(3)

 

SSRF安全指北

 

可以看到,对于@qq.com来说,urllib3取到的host是baidu.com,而urllib取到的host是qq.com。笔者曾就此问题与python官方联系过,但是官方并不认为这是一个安全问题,表示urllib3与chrome浏览器的解析保持一致(将视为/),所以这个问题会一直存在。如果在check_ssrf中解析url函数用的是urllib3,而业务代码发送请求时采用的是urllib,两者之间的解析差异就会导致绕过的情况。

这里多说一句,其实url解析问题涉及到了web安全的底层逻辑,不仅仅是在ssrf中有利用,其危害范围很广,包括不限于url跳转,oauth认证,同源策略(如postMessage中origin的判断)等一切会涉及到host判断的场景。

3.3 DNS rebinding

从SSRF修复方案来看,这里流程中进行了两次DNS解析,第一次在check_ssrf的时候会对URL的host进行DNS解析,第二次在do_curl请求时进行解析。这两次DNS解析是有时间差的,我们可以使用这个时间差进行绕过。

时间差对应DNS中的机制是TTL。TTL表示DNS里面域名和IP绑定关系的Cache在DNS上存活的最长时间。即请求了域名与iP的关系后,请求方会缓存这个关系,缓存保持的时间就是TTL。而缓存失效后就会删除,这时候如果重新访问域名指定的IP的话会重新建立匹配关系及cache。

当我们设置TTL为0时,当第一次解析域名后,第二次会重新请求DNS服务器获取新的ip。DNS重绑定攻击的原理是:利用服务器两次解析同一域名的短暂间隙,更换域名背后的ip达到突破同源策略或过waf进行ssrf的目的。

这里利用方法如下:

 

在网站 SSRF 漏洞处访问精心构造的域名。网站第一次解析域名,获取到的IP地址为A;

 

 

经过网站后端服务器的检查,判定此IP为合法IP。

 

 

网站获取URL对应的资源(在一次网络请求中,先根据域名服务器获取IP地址,再向IP地址请求资源),第二次解析域名。此时已经过了ttl的时间,解析记录缓存IP被删除。第二次解析到的域名为被修改后的 IP 即为内网IP B;

 

 

攻击者访问到了内网IP。

 

当然,上述情况是最理想的情况,在不同的语言,不同服务器中也存在差异:

 

java中DNS请求成功的话默认缓存30s(字段为cache.ttl,默认情况下没有设置),失败的默认缓存10s。(缓存时间在 /Library/Java/JavaVirtualMachines/jdk /Contents/Home/jre/lib/security/java.security 中配置)

 

 

在php中则默认没有缓存。

 

 

Linux默认不会进行DNS缓存,mac和windows会缓存(所以复现的时候不要在mac、windows上尝试)

 

 

有些公共DNS服务器,比如114.114.114还是会把记录进行缓存,但是8.8.8.8是严格按照DNS协议去管理缓存的,如果设置TTL为0,则不会进行缓存。

 

在传统的SSRF修复方案中,由于java会存在默认的dns缓存,所以一般认为java不存在DNS rebinding问题。但是试想这么一个场景,如果刚刚好到了DNS缓存时间,此时更新DNS缓存,那些已经过了SSRF Check而又没有正式发起业务请求的request,是否使用的是新的DNS解析结果。其实理论上只要在发起第一次请求后等到30秒之前的时候再请求即可,但为了保证效果,可以在28s左右,开始以一个较短的时间间隔去发送请求,以达到时间竞争的效果。相关示例代码可参考附录三。

Dns rebinding常见方案除了自建dns服务器之外,还可以通过绑定两个A记录,一个绑定外网ip,一个绑定内网ip。当然这种情况访问顺序是随机的,无法保证成功率。

自建dns服务器需要将域名的dns服务指向自己的vps,然后在vps上运行dns_server脚本,dns_server.py内容如下

 

SSRF安全指北

 

效果如下:

 

SSRF安全指北

 

当第一次访问时,解析为外网ip通过ssrf检测,

第二次访问时,也即业务访问时,ip会指向127.0.0.1,从而达到了绕过目的。

除此之外,还有一些绕过技巧,例如利用IPv6,

说点什么吧
  • 全部评论(0
    还没有评论,快来抢沙发吧!