DNS-Rebinding攻击
前言
还是接着上次的SSRF来说,今天重点放在绕过手法之DNS-Rebinding
前置
浏览器同源策略
简单来说,就是同一个域名下的网站只能调用本域名下的资源,比如 http://www.ab.com/index.php 只能调用 http://www.ab.com/index2.php的资源,而不能调用 http://www.def.com/ 下的资源。(<script>,<link>,<iframe>,<img>等标签的SRC属性除外
DNS的TTL
DNS的TTL值记录了解析记录的缓存可以存在的时间,比如一开始你想访问 www.myangswhitehat.cn ,我们的主机会向最近的DNS服务器发起请求,查找这个域名对应的IP,这个DNS服务器上可能没有,这个时候会采取递归的查询去找到,然后返回给我们的主机。
而短时间内我们还是访问同一个域名的时候,这个时候再重新递归搜索一次就很麻烦了,所以DNS服务器直接给我们记录了这个解析,而TTL就代表这个解析能够存在的时间,时间过了,又要开始递归搜索了。
DNS-rebinding
攻击原理
简单来说,就是利用两次DNS查询解析的差异来完成攻击,当然也是利用了时间差。
具体攻击原理一张图就可以说明了(对请求一定程度上作了简化

利用场景
好了,接下来才进入我们的正题。我们用一段代码来引出这个DNS-rebinding的利用场景:
1 | $dst = @$_GET['KR']; |
一开始我们输入的KR域名会经过DNS查询解析,然后赋值给ip变量,然后去判断ip是不是等于’54.87.54.87’ ,如果是,则在file_get_contents()函数这里,就会再一次进行dns查询获取ip,然后去拿到它的内容。可以发现前后进行了两次DNS查询解析。
而如果我们是想访问内网的资源,那ip这里最后肯定得是内网的。
再来看一个例子(ctfhub-ssrf)
1 |
|
这个地方也是一开始 gethostbyname 经过了一个dns解析,后面curl发送请求的时候,又会经历一次,也是经历了两次。
攻击方式
所以我们的着重点就是如何让两次请求返回不一样的IP
第一种方式 :将两个IP都指向同一个域名,同时得保证 TTL很小,这里有一个在线网站可以做到:
https://lock.cmpxchg8b.com/rebinder.html?tdsourcetag=s_pctim_aiomsg
因为如果两个IP都指向同一个域名,解析的时候会随机返回,也并不是交替返回。
所以碰撞成功的概率为 1/4 (第一次为我们用来绕过的IP,第二次为内网的IP)
第二种方式(自建DNS服务器,未复现成功
一开始没复现成功,上次在跑模拟redis服务器的脚本时候,发现端口放行这个问题,今天猛地想起,之前复现自制服务器没成功,可能也是因为这个问题,所以今天复现成功了。
第二种方式就是自己建一个DNS服务器,并且控制当第一次被请求时,返回一个IP,第二次被请求时返回另外一个IP,就避免了去碰撞。
需要在自己的VPS上添加两条解析:

NS记录表示 test.myangswhitehat.cn 这个域名由 ns.myangswhitehat.cn 这个域名所在的服务器进行DNS解析,而A记录表示 ns.myangswhitehat.cn 这个域名在106.54.90.137 上,所以最后 test.myangswhitehat.cn 实质上由 106.54.90.137 来解析。
然后我们在106.54.90.137上运行DNS脚本:
1 | from twisted.internet import reactor, defer |
效果图

最后我以ctfHUB上SSRF重绑定作了测试:
http://challenge-50e3dc7ff9cd8d8e.sandbox.ctfhub.com:10080/?url=test.myangswhitehat.cn/flag.php 成功拿到flag:
