本文主要介绍SSRF漏洞受到各种限制时,常见的绕过姿势。

(图片来自 SSRF漏洞Bypass技巧)
0x00 URL scheme

第一部分:协议名(以单个冒号结束)
第二部分:用户信息 也就是账号密码!(登陆ftp时常用)
第三部分:主机名(也就是域名)
第四部分:端口
第五部分:查询内容,包含【path+param】,这里有个bug。应该是?号后的内容才是查询!
第六部分:Fragment ID(不会发送到服务器!)
1.提取协议名:
他会查找第一个 : 号在哪,如果找到了,那么: 号左边的便是协议名!
如果获得的协议名中出现了不该有的字符,那么认为这可能就是个相对的url ,获得的并不是协议名!
2.去除层级url标记符:
字符串 // 应该算跟在协议名后面的 如果发现有该字符 则会跳过该字符 如果没有找到便不管了!所以 http:baidu.com 也是可以访问的! 浏览器中还可以用反斜杠来代替正斜杆 \\ 代替 // firefox除外!
0x01 浏览器解析特性
1. @
简单来说,正常的web应用处理是这样的:
先使用parse_url对用户传入的URL解析,获取到host,将host传入check_inner_ip,检查是否是内网IP。
如果检查通过,则将URL传给HTTP库发送请求。
所以绕过的核心原理是,parse_url时获取的host是A,实际使用HTTP库(如curl)发包时,他内部获取的host是B,利用这两个差异绕过check_inner_ip。
这个差异通常是二者使用的URL解析逻辑不同导致的。比如,PHP使用CURL发送请求,而CURL底层实际上是个第三方库。那么PHP自己的parse_url,和CURL库内部的“parse_url”,就可能存在差异。
http://xss1.com&action=test@www.baidu.com
@External_Domain@12.0.0.1
Chrome不可以!
2. 句号
127。0。0。1 >>> 127.0.0.1

3. # ?
#.jpg
?.jpg
截断!详见一次实战代码审计

0x02 PunnyCode
因为操作系统的核心都是英文组成,DNS服务器的解析也是由英文代码交换,所以DNS服务器上并不支持直接的中文域名解析,所有中文域名的解析都需要转成punycode码,然后由DNS解析punycode码。其实所说和各种浏览器完美支持中文域名,只是浏览器软件里面主动加入了中文域名自动转码,不需要原来的再次安装中文域名转码控件来完成整个流程。
例如:企鹅.com,用Punycode转换后为:xn–hoq754q. com
中国.cn,用Punycode转换后为:xn–fiqs8s. cn
ⅅʳºℙˢ --> drops
ʷººʸⓊⁿ —> wooyun
Ⓞʳℊ —> org
ⅅʳºℙˢ.ʷººʸⓊⁿ.ºʳℊ --> drops.wooyun.org
0x03 进制转换
http://664552783 => http://baidu.com
$ ping baidu.com
Pinging baidu.com [39.156.69.79] with 32 bytes of data:
十进制
39.156.69.79 => 664552783(十进制)
八进制
39.156.69.79 => 04747042517 (八进制)
Octal,是一种计数法,采用0,1,2,3,4,5,6,7八个数码,逢八进位,并且开头一定要以数字0开头。

还有一种,IPV6形式
[0:0:0:0:0:ffff:127.0.0.1]
::ffff:7f00:1
0:0::1
0:0:0:0:0:0:0:0
以及特殊形式http://0/
0x04 短网址

实际是基于302跳转的

个人常用的短网址服务
suo.im
tinyurl.com
goo.gl
...
0x05 xip.io / xip.name
xip.name
类似于一个"转发"的东西,绕过关键词白名单时很好用,如 if "baidu" in URL: {visit(URL);}

xip.io****

127.0.0.1.xip.io >>> 127.0.0.1
www.baidu.com.127.0.0.1.xip.io >>> 127.0.0.1
...
类似的服务,还有
lvh.me
*.localtest.me (see:readme.localtest.me )
ping 1.2.3.4.sslip.io
ping 1.1.2.3.nip.io
0x06 Enclosed alphanumerics

ⓔⓧⓐⓜⓟⓛⓔ.ⓒⓞⓜ >>> http://example.com
ⓑⒶⒾⒹⓤ。Cⓞm >>> http://baidu.com

①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳⑴⑵⑶⑷⑸⑹⑺⑻⑼⑽⑾⑿⒀⒁⒂⒃⒄⒅⒆⒇⒈⒉⒊⒋⒌⒍⒎⒏⒐⒑⒒⒓⒔⒕⒖⒗⒘⒙⒚⒛⒜⒝⒞⒟⒠⒡⒢⒣⒤⒥⒦⒧⒨⒩⒪⒫⒬⒭⒮⒯⒰⒱⒲⒳⒴⒵ⒶⒷⒸⒹⒺⒻⒼⒽⒾⒿⓀⓁⓂⓃⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ⓪⓫⓬⓭⓮⓯⓰⓱⓲⓳⓴⓵⓶⓷⓸⓹⓺⓻⓼⓽⓾⓿
0x07 内网地址
通常我们会将以下三个段设置为内网IP段,所有内网内的机器分配到的IP是在这些段中:
完整列表参考https://datatracker.ietf.org/doc/html/rfc5735
- RFC 5735😂
192.168.0.0/16 => 192.168.0.0 ~ 192.168.255.255
10.0.0.0/8 => 10.0.0.0 ~ 10.255.255.255
172.16.0.0/12 => 172.16.0.0 ~ 172.31.255.255
127.0.0.0/8
所以通常,我们只需要判断目标IP不在这三个段,另外还包括 127.0.0.0/8 和 0.0.0.0/8
- 本地地址不但可以用常见的
127.0.0.1表示,还可以用127.6.6.6来表示- 在Linux下,
127.0.0.1与0.0.0.0都指向本地,参考 http://blog.orange.tw/2017/07/how-i-chained-4-vulnerabilities-on.html
Some Practices
一些小练习
第一弹: 欲盖弥彰
①②⑦。⓪。⓪。①


第二弹: 偷天换日
http://qq.com?action=submit&ID=@04747042517

加个高亮就更清楚
http://qq.com?action=submit&ID=@04747042517
注意
- ?号,是中文的问号
- @,才是最关键的,后面0开头的字符串,是八进制表示的IP地址,前面的都是userinfo
DNS rebinding 重绑定
1. DNS请求过程
- 查询本地DNS服务器(/etc/resolv.conf)
- 如果有缓存,返回缓存的结果,不继续往下执行
- 如果没有缓存,请求远程DNS服务器,并返回结果
平时使用的MAC和Windows电脑上,为了加快HTTP访问速度,系统都会进行DNS缓存。但是,在Linux上,默认不会进行DNS缓存(https://stackoverflow.com/questions/11020027/dns-caching-in-linux) ,除非运行nscd等软件。
不过,知道Linux默认不进行DNS缓存即可。这也解释了,我为什么同样的配置,我在MAC上配置不成功,Linux上配置可以。
需要注意的是,IP为8.8.8.8的DNS地址,本地不会进行DNS缓存。
Java默认不存在被DNS Rebinding绕过风险(TTL默认为10)
PHP默认会被DNS Rebinding绕过
Linux默认不会进行DNS缓存
DNS请求过程
- 查询本地DNS服务器(/etc/resolv.conf)
- 如果有缓存,返回缓存的结果,不继续往下执行
- 如果没有缓存,请求远程DNS服务器,并返回结果
2. 重绑定实现过程



其实,知道创宇的ceye.io平台中,也有DNS Rebinding服务


实战时,用r.xxxxx.ceye.io即可
第一次请求,返回127.0.0.1
$ nslookup r.abcdef.ceye.io
Server: 8.8.8.8
Address: 8.8.8.8#53
Non-authoritative answer:
Name: r.abcdef.ceye.io
Address: 127.0.0.1
第二次请求,返回192.168.0.1
$ nslookup r.abcdef.ceye.io
Server: 8.8.8.8
Address: 8.8.8.8#53
Non-authoritative answer:
Name: r.abcdef.ceye.io
Address: 192.168.0.1
3. 一个不容忽视的前提
目标使用的DNS服务器,会影响DNS Rebinding攻击的效果。因此如果要成功进行DNS Rebinding攻击,必须目标使用了遵守TTL规则的DNS服务器。
常用的public dns:
- 遵守DNS TTL规则的有: 8.8.8.8
- 未遵守规则的有:1.1.1.1、223.5.5.5、119.29.29.29
- 是否缓存DNS记录比较随性的有:114.114.114.114
可见,大部分DNS为了节省请求数量,都会缓存DNS记录,只有8.8.8.8对TTL实现的比较理想。
4. 利用工具
可以采用[https://github.com/taviso/rbndr](https://github.com/taviso/rbndr)来进行DNS rebinding
# 在255.255.255.255与外网ip之间切换
ffffffff.2FF02E9A.rbndr.us
# 在127.0.0.1与外网ip之间切换
7F000001.2FF02E9A.rbndr.us


CTF风格的一些题
WMCTF2020-SimpleAuth
输入url参数后,提示只支持http协议。

构造url请求自己vps的http端口,可以成功收到http请求。

响应正常http时,页面显示nothing,接着可以【尝试修改http响应包】进行测试,比如返回401认证。
<?php
header('WWW-Authenticate: Basic realm="test"');
header('HTTP/1.0 401 Unauthorized');
?>
当响应401认页面的内容发现了变化,提示不支持该认证类型。通过【查阅资料】得知HTTP支持Basic、Digest、NTLM等认证类型,从网站信息中得知网站为Windows服务器。尝试响应NTLM类型的401认证。
<?php
header('WWW-Authenticate: NTLM');
header('HTTP/1.0 401 Unauthorized');
?>
重新请求发现响应内容发现了变化。
通过tcpdump抓包可以看到,当http响应头要求NTLM认证时,题目会通过http NTLM认证再次请求url。
后记:SSRF实战与理论
知乎主站一处SSRF漏洞可探测内网
来源
【漏洞学习——SSRF】知乎主站一处SSRF漏洞可探测内网 https://blog.csdn.net/Fly_hps/article/details/84400273
漏洞描述
知乎回答问题的时候,输入网址将自动被转换为标题。比如输入http://wooyun.org/,将会变成:

明显是后台进行了请求。
抓包,发现是请求的http://www.zhihu.com/scraper:

低危SSRF提权进内网
来源
R3start 低危SSRF提权进内网
漏洞描述
通过SSRF点,进入内网,最终在Redis中反复乱杀
WordPress SSRF(DNS Rebinding)
参考资料
- 利用 Gopher 协议拓展攻击面 https://blog.chaitin.cn/gopher-attack-surfaces/
- SSRF漏洞的利用与攻击内网应用实战 https://xz.aliyun.com/t/7405#toc-0
- URL Hacking - 前端猥琐流 https://wooyun.js.org/drops/URL%20Hacking%20-%20%E5%89%8D%E7%AB%AF%E7%8C%A5%E7%90%90%E6%B5%81.html

