CC6反序列化链
CC6不受 JDK 版本限制的入口替换链CC6 可以看成 CC1 的入口替换版。后半段的触发、串联和执行能力基本原样保留变化点集中在反序列化入口由谁在readObject()阶段把调用送进攻击者可控的Map。1. 适用条件JDK版本不受版本限制组件版本commons-collections 3.1 ~ 3.2.12. JDK 更新限制了 AnnotationInvocationHandler 的自动调用能力CC1 链分为写时触发链和读时触发链入口集中在同一个位置sun.reflect.annotation.AnnotationInvocationHandler.readObject()以下简称 AIH。两条链的区分在触发动作写时触发链的入口动作是一次写入entry.setValue(...)读时触发链的入口动作是一次读取LazyMap.get()。AIH 的readObject()方法会遍历一张注解成员名 - 成员值的表并据此接入 CC1 的两条链读时触发链memberValues.entrySet()- 触发 map 代理类的 AIHinvoke()-LazyMap.get()-ChainedTransformer.transform()写时触发链成员值类型不匹配时调用entry.setValue(...)-TransformedMap.checkSetValue()-valueTransformer.transform()这个方法在 JDK 8u71 被整体重写两个版本对比如下。JDK 7u21 中的实现s.defaultReadObject();...for(Map.EntryString,ObjectmemberValue:memberValues.entrySet()){// ▶ 遍历攻击者可控的 memberValuesStringnamememberValue.getKey();Class?memberTypememberTypes.get(name);if(memberType!null){ObjectvaluememberValue.getValue();if(!(memberType.isInstance(value)||valueinstanceofExceptionProxy)){memberValue.setValue(// ▶ 写时链触发点newAnnotationTypeMismatchExceptionProxy(value.getClass()[value]).setMember(annotationType.members().get(name)));}}}JDK 8u71 中的实现ObjectInputStream.GetFieldfieldss.readFields();...MapString,ObjectstreamVals(MapString,Object)fields.get(memberValues,null);...MapString,ObjectmvnewLinkedHashMap();for(Map.EntryString,ObjectmemberValue:streamVals.entrySet()){// ▶ 遍历仍在StringnamememberValue.getKey();Objectvaluenull;Class?memberTypememberTypes.get(name);if(memberType!null){valuememberValue.getValue();if(!(memberType.isInstance(value)||valueinstanceofExceptionProxy)){valuenewAnnotationTypeMismatchExceptionProxy(...)...;}}mv.put(name,value);}UnsafeAccessor.setMemberValues(this,mv);区别不只是少了一行setValue(...)。旧版readObject直接在攻击者可控的memberValues上原地修值新版readObject把成员值先复制进一张新建的LinkedHashMap最后通过Unsafe写回字段。写时触发链所依赖的那次自动setValue(...)调用自此消失。这次重写到底拦了什么、没拦什么它拦的是 readObject() 阶段那次原地修值的自动调用setValue 已移除 它没拦的是 Commons Collections 包里的任何类—— LazyMap、ChainedTransformer、InvokerTransformer 均未受影响 它留下的是 streamVals.entrySet() 这次遍历仍以某种形式存在 但已经只是 JDK 内部类的实现细节对应出处AnnotationInvocationHandler.javajdk7u21-b11AnnotationInvocationHandler.javajdk8u71-b153. 链上还保留着触发、串联和执行能力入口被限制不等于整条链子都失效了。JDK 修改的是自己包里的一个内部类Commons Collections 包中的组件并未受影响CC1 积累下来的能力大部分仍然成立类承担的能力LazyMap缺失 key 时把get()接进transform()触发能力ChainedTransformer把多个Transformer串成一条调用链串联能力ConstantTransformer给链一个固定起点InvokerTransformer单步方法调用后半段执行手段后半段原样可用LazyMap.get(key) - ChainedTransformer.transform(key) - ConstantTransformer(Runtime.class) - InvokerTransformer(getMethod) - InvokerTransformer(invoke) - InvokerTransformer(exec)从LazyMap.get()到Runtime.exec()这一整段都不需要重新分析。只需要补齐自动调用的入口就可以把链串起来。4. 链的前半段缺少把调用接进可控 Map 的入口能力反序列化阶段缺的是一次自动发生的方法调用作用在攻击者可控的对象上并最终落到LazyMap.get()。缺口可以分成两个半块1. 自动调用点某个 Serializable 类的 readObject() 里 自动对攻击者可控对象调用一个方法 2. 桥存在一个对象把这次方法调用的内部 转成 map.get(key)CC1 中这两块分别由AnnotationInvocationHandler.readObject()和动态代理 按方法名取值承担。第一块已不可靠第二块本身未被修改但它是为了承接entrySet()这次特定调用而引入的——调用点发生变化桥接也需要随之更换。还有一个更隐蔽的要求。这次要找的自动调用不能再是反序列化之后附加的修正动作——这类动作一次修补即可删除。它应当是某个数据结构在重建时不可省略的步骤删掉它这个类自身便不再成立。5. 反序列化期的自动 hashCode 调用成为新的入口方向沿不可省略的步骤往下找候选范围收窄到容器类。哈希容器在readObject()中的工作本质是把流中的 key-value 重新摆回桶中。摆放位置由 key 的哈希值决定因此对每个 key 调用一次hashCode()不是附加动作而是重建哈希表的必经步骤。只要这个类仍是哈希表这一步就在任何版本都无法删除。HashMap正是如此。JDK 8 中它的readObject()末尾for(inti0;imappings;i){Kkey(K)s.readObject();Vvalue(V)s.readObject();putVal(hash(key),key,value,false,false);}hash(key)的第一步就是调用key.hashCode()staticfinalinthash(Objectkey){inth;return(keynull)?0:(hkey.hashCode())^(h16);}JDK 7 写法不同动作相同putForCreate()中先计算hash(key.hashCode())。版本之间实现细节屡有变化这次调用始终存在。这一判断可以逐版本核实JDK 17 中的hash()与putVal()和 JDK 8 完全一致HashMap、HashSet自 JDK 1.2 引入重算哈希是重建自身的固有步骤不存在被修补删除的理由。入口一侧CC6 不受 JDK 版本限制。第一块支点至此确定HashMap这类反序列化时会重建哈希结构的容器。尚缺第二块一个hashCode()内部自带map.get(key)的对象把这次哈希计算桥接进LazyMap。对应出处HashMap.javajdk8uHashMap.javajdk17u6. 替代支点开始收敛出来先补第二块把hashCode()桥接到map.get(key)[读时触发链LazyMap.get()]的对象。符合这个条件的是org.apache.commons.collections.keyvalue.TiedMapEntry它把一张Map和一个 key 绑在一起充当这张表的一个条目。关键在两处方法publicObjectgetValue(){returnmap.get(key);}publicinthashCode(){ObjectvaluegetValue();return(getKey()null?0:getKey().hashCode())^(valuenull?0:value.hashCode());}hashCode()为了计算条目哈希需要先取得条目的值取值的方式就是map.get(key)TiedMapEntry.hashCode() - getValue() - map.get(key) // map 换成 LazyMap就是 LazyMap.get(key)构造时将LazyMap和一个不存在的 key 绑入之后任何一次对该条目的哈希计算都会进入LazyMap的懒加载分支ChainedTransformer被带起。此外TiedMapEntry的equals()与toString()内部同样调用getValue()可桥接的调用不止hashCode()一种CC5 走的是toString()一路。出处commons-collections-3.2.1-sources.jar中的TiedMapEntry.java第一块支点上一节已经确定。ysoserial 在HashMap外再包一层HashSetHashSet本身不存数据内部委托给一张HashMap其readObject()逐个读出元素后执行map.put(e, PRESENT)同样落到HashMap.put() - hash(key) - key.hashCode()。对应出处HashSet.javajdk8u两块支点都确定后拼合时会遇到一个新问题链在构造时就会先执行一遍。组装 payload 时总要执行一步map.add(entry)或map.put(entry, ...)。向哈希容器中放入元素当场就要计算entry.hashCode()——这次计算发生在攻击者自己的机器上后果有两个1. 链提前触发命令在构造 payload 的进程中被先执行 2. 链在目标侧失效LazyMap.get() 会把生成的值回填进 innerMap 反序列化时再 get 同一个 key命中缓存 懒加载分支不会再走因此构造时的核心要求是组装过程中的任何时刻都不能真正对TiedMapEntry执行哈希计算。ysoserial 的做法是把放入和替换拆成两步先向HashSet中放入一个无害的占位对象再通过反射沿内部结构把占位 key 原地换成TiedMapEntry多版本兼容的 try/catch 分支略TiedMapEntryentrynewTiedMapEntry(lazyMap,foo);HashSetmapnewHashSet(1);// 变量名沿用 ysoserial 原文类型为 HashSetmap.add(foo);// 先放无害占位 keyString 的 hashCode 与链无关// 反射HashSet.map - HashMap.table - 节点.keyFieldfHashSet.class.getDeclaredField(map);...HashMapinnimpl(HashMap)f.get(map);Fieldf2HashMap.class.getDeclaredField(table);...Object[]array(Object[])f2.get(innimpl);Objectnodearray[0]null?array[1]:array[0];FieldkeyFieldnode.getClass().getDeclaredField(key);...keyField.set(node,entry);// 占位 key 原地换成 TiedMapEntry整个构造过程中TiedMapEntry.hashCode()一次也未执行序列化时HashMap按桶序写出键值反序列化时重建流程重新对每个 key 计算哈希——链只在目标侧执行。出处ysoserial CommonsCollections6.java另一种常见写法思路相同只是替换的位置不同先塞一个空的ChainedTransformer到LazyMap让构造时那次hashCode()空转序列化前再通过反射设置一个带payload的 transformer 数组并清除回填进innerMap的 key。7. CC6 由此重新成立把入口、桥接和 CC1 留下的后半段接起来CC6 的完整链路不包HashSet、直接使用HashMap.readObject() - putForCreate / putVal的版本链路结构一致。CC1 和 CC6 的前半段对比CC6 保留 CC1 的触发、串联和执行能力把入口从AnnotationInvocationHandler的版本相关行为换成哈希容器重建结构时对 key 的必然hashCode()调用再用TiedMapEntry把这次调用桥进LazyMap.get()。

相关新闻

AI生成产品展示图:97%的设计师不知道的5个合规避坑技巧,今天不看明天被下架!

AI生成产品展示图:97%的设计师不知道的5个合规避坑技巧,今天不看明天被下架!

更多请点击: https://intelliparadigm.com 第一章:AI生成产品展示图:合规风险的底层逻辑 AI生成产品展示图正迅速渗透电商、广告与品牌营销场景,但其背后潜藏的合规风险并非源于技术缺陷,而根植于数据来源、生成机制与…

2026/7/30 1:39:28阅读更多 →
空调PTC电辅热原理与使用指南:制热效果与耗电实测

空调PTC电辅热原理与使用指南:制热效果与耗电实测

1. 先搞清楚 PTC 电辅热到底解决空调制热的什么问题空调制热时,室外温度越低,传统热泵从室外吸热就越困难。很多人在冬天开空调会发现制热效果差、升温慢,甚至室外机结霜导致频繁停机除霜。PTC 电辅热就是在这种场景下介入的辅助加热方案。它…

2026/7/30 1:39:28阅读更多 →
从零设计八路抢答器:单片机方案、硬件电路与软件状态机实战

从零设计八路抢答器:单片机方案、硬件电路与软件状态机实战

1. 项目缘起:从课堂到赛场的“抢答”需求在各类知识竞赛、课堂互动、企业培训甚至家庭游戏中,“抢答”都是一个能瞬间点燃气氛、检验反应与知识储备的核心环节。一个稳定、公平、直观的抢答系统,是保证活动顺利进行的关键。然而,市…

2026/7/30 1:39:28阅读更多 →
Python开发环境搭建与VScode配置全攻略:从零到运行第一个程序

Python开发环境搭建与VScode配置全攻略:从零到运行第一个程序

1. 项目概述:为什么环境搭建是Python入门的“第一道坎”?很多新手朋友拿到Python教程,兴冲冲地打开第一课,结果上来就被“环境搭建”四个字给劝退了。命令行、环境变量、解释器、IDE……一堆陌生的术语砸过来,感觉比学…

2026/7/30 2:57:21阅读更多 →
Java并发控制组件:从基础到高级实战指南

Java并发控制组件:从基础到高级实战指南

1. Java并发控制组件概述在当今高并发的互联网应用中,Java并发控制组件已经成为开发者必须掌握的核心技能之一。作为一名长期奋战在一线的Java开发者,我见证了从早期synchronized到现代并发工具包的演进历程。这些组件不仅仅是面试中的"八股文"…

2026/7/30 2:57:21阅读更多 →
BatchDate(照片批量添加日期工具) v1.0.0.0一款功能强大的批量给图片添加日期及文字软件

BatchDate(照片批量添加日期工具) v1.0.0.0一款功能强大的批量给图片添加日期及文字软件

BatchDate照片批量添加日期工具:自定义日期水印,让每一张照片留下时间印记大家好,我是大飞哥。数码相机和智能手机的普及让我们每年都会积累成千上万张照片——孩子的成长记录、家庭旅行的美好瞬间、重要活动的现场留影。然而这些珍贵的照片文…

2026/7/30 2:57:20阅读更多 →
机器学习算法解析与实战应用指南

机器学习算法解析与实战应用指南

1. 机器学习基础概念与核心价值机器学习作为人工智能的核心分支,正在深刻改变我们处理数据的方式。简单来说,它是让计算机系统通过数据自动"学习"和"改进"的技术,而不需要显式编程。想象一下教孩子识别动物:你…

2026/7/30 2:57:20阅读更多 →
「久坐克星・健康护航」—— 智能桌面久坐提醒器 v1.3.AI 健康监测内置颈肩操健康管理软件

「久坐克星・健康护航」—— 智能桌面久坐提醒器 v1.3.AI 健康监测内置颈肩操健康管理软件

大家好,我是大飞哥。现代职场人每天在电脑前久坐超过8小时已成常态,而医学研究早已证实,连续久坐超过60分钟,身体的新陈代谢便会开始放缓,腰椎、颈椎、眼部及心血管系统均承受着不可逆的累积损伤。我们常常在工作投入时…

2026/7/30 2:57:20阅读更多 →
终极指南:VSCode Mermaid Preview高效图表可视化解决方案

终极指南:VSCode Mermaid Preview高效图表可视化解决方案

终极指南:VSCode Mermaid Preview高效图表可视化解决方案 【免费下载链接】vscode-mermaid-preview Previews Mermaid diagrams 项目地址: https://gitcode.com/gh_mirrors/vs/vscode-mermaid-preview 在当今技术文档编写和系统设计过程中,图表可…

2026/7/30 2:55:19阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/7/29 9:47:45阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/29 7:00:19阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/29 7:58:51阅读更多 →
3分钟解锁iOS应用自由:TrollInstallerX让你的iPhone摆脱安装限制 [特殊字符]

3分钟解锁iOS应用自由:TrollInstallerX让你的iPhone摆脱安装限制 [特殊字符]

3分钟解锁iOS应用自由:TrollInstallerX让你的iPhone摆脱安装限制 🚀 【免费下载链接】TrollInstallerX A TrollStore installer for iOS 14.0 - 16.6.1 项目地址: https://gitcode.com/gh_mirrors/tr/TrollInstallerX 你是否曾经因为iOS系统的严格…

2026/7/30 0:00:58阅读更多 →
[GESP202606 四级] 扫雷

[GESP202606 四级] 扫雷

B4557 [GESP202606 四级] 扫雷 https://www.luogu.com.cn/problem/B4557 中国计算机学会(CCF)2026年6月C四级讲解——扫雷 https://www.bilibili.com/video/BV1MCMg6AEXR/ B4557 [GESP202606 四级] 扫雷 https://www.bilibili.com/video/BV1ZKTj6ZEVh/ 2…

2026/7/30 0:00:58阅读更多 →
Windows驱动存储终极清理工具:DriverStoreExplorer完全指南

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南 【免费下载链接】DriverStoreExplorer Driver Store Explorer 项目地址: https://gitcode.com/gh_mirrors/dr/DriverStoreExplorer 您是否曾因Windows系统盘空间不足而烦恼?是否遇到过设…

2026/7/30 0:00:58阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/30 0:27:26阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/29 4:31:51阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/29 14:26:42阅读更多 →