文章总结: 本文深度解析Java反序列化CommonsCollections组件的五大经典利用链,详细拆解CC1至CC7的触发原理与核心差异。文章揭示了Java对象模型过度信任输入的设计缺陷,并提出升级依赖、实施反序列化白名单及部署WAF/RASP等防御建议,旨在帮助安全研究者深入理解漏洞本质与防御策略。 综合评分: 85 文章分类: 漏洞分析,WEB安全,渗透测试,代码审计,CTF
第109天-深度解析Java反序列化:揭秘Commons Collections五大Gadget Chain
原创
Сяо Яо Сяо Яо
AlphaNet
2026年3月26日 16:50 韩国
🚀 引言:当Java反序列化遇到“Gadget”
嗨,各位未来的安全研究者们!👋
在Java安全领域里,有一个绕不开的经典话题——反序列化漏洞(Deserialization Vulnerability)。它不像SQL注入那样直观,也不像XSS那样容易理解,但一旦被成功利用,往往直接就是远程代码执行(RCE),危害极高。
而在这个漏洞体系中,有一个“传奇级组件”反复登场——commons-collections。
这个看似普通的工具库,却隐藏着大量可被利用的“代码片段”,也就是:
Gadget(利用片段)
当攻击者把这些 Gadget 精心拼接,就会形成:
💣 Gadget Chain(利用链)
今天这篇文章,我们将彻底拆解最经典的五条链:
👉 CC1 / CC2 / CC4 / CC5 / CC7
不仅讲清楚“是什么”,更重点讲透:
-
为什么能打
-
怎么串起来
-
本质设计缺陷在哪
🧠 一、Gadget Chain 三要素(必须搞懂)
所有反序列化利用链,本质都是这三部分:
1️⃣ 入口点(Source)
触发点,一般是:
readObject()
当你反序列化时自动调用。
2️⃣ 调用链(Gadget Chain)
一连串“正常类方法”:
A -> B -> C -> D -> ...
看起来合法,其实在偷偷推进攻击。
3️⃣ 执行点(Sink)
最终危险操作:
Runtime.getRuntime().exec()
或者:
-
反射调用
-
类加载执行
-
脚本执行
📌 一句话总结:
反序列化漏洞 = 可控输入 + 自动触发 + 链式调用 + 危险执行
🔥 二、五大经典利用链深度解析
🔗 CC1:开山鼻祖(TransformedMap)
💡 核心思想
利用:
-
TransformedMap -
ChainedTransformer
在 setValue 时自动触发 transform
🔗 调用链
ObjectInputStream.readObject()
-> AnnotationInvocationHandler.readObject()
-> MapEntry.setValue()
-> TransformedMap.checkSetValue()
-> ChainedTransformer.transform()
-> ConstantTransformer
-> InvokerTransformer
-> InvokerTransformer
-> InvokerTransformer
-> Runtime.exec()
🧠 本质漏洞
👉 “数据操作”被设计成“执行逻辑”
🔗 CC2:PriorityQueue + TemplatesImpl
💡 核心思想
利用:
-
PriorityQueue自动排序 -
Comparator被调用 -
触发
TemplatesImpl
🔗 调用链
PriorityQueue.readObject()
-> heapify()
-> siftDown()
-> Comparator.compare()
-> InvokerTransformer
-> TemplatesImpl.newTransformer()
-> defineClass()
⚠️ 关键突破
👉 不再直接 exec,而是:
加载恶意字节码
🔗 CC4:InstantiateTransformer 变种
💡 核心变化
替换:
InvokerTransformer → InstantiateTransformer
🔗 调用链
PriorityQueue.readObject()
-> Comparator.compare()
-> ChainedTransformer
-> ConstantTransformer
-> InstantiateTransformer
-> TrAXFilter()
-> TemplatesImpl.newTransformer()
📌 优势:
-
更灵活
-
绕过部分检测
🔗 CC5:BadAttributeValueExpException
💡 核心思想
利用:
toString()
在反序列化中被调用
🔗 调用链
readObject()
-> BadAttributeValueExpException.readObject()
-> toString()
-> TiedMapEntry
-> LazyMap.get()
-> ChainedTransformer
-> Runtime.exec()
📌 关键点:
👉 “打印对象”也能触发漏洞
🔗 CC7:Hashtable 触发 equals
💡 核心思想
利用:
Hashtable.readObject()
内部触发:
equals()
🔗 调用链
Hashtable.readObject()
-> reconstitutionPut()
-> equals()
-> LazyMap.get()
-> ChainedTransformer
-> Runtime.exec()
📌 关键点:
👉 Map结构操作触发执行链
🧬 三、核心差异总结
| 利用链 | 入口点 | 触发方式 | 执行方式 | | — | — | — | — | | CC1 | AnnotationInvocationHandler | setValue | 反射 exec | | CC2 | PriorityQueue | compare | 字节码加载 | | CC4 | PriorityQueue | compare | 构造函数触发 | | CC5 | BadAttributeValueExpException | toString | LazyMap | | CC7 | Hashtable | equals | LazyMap |
🛡️ 四、防御方案(重点!)
✅ 1. 升级依赖(最有效)
-
commons-collections 3.2.2+
-
commons-collections4 4.1+
✅ 2. 反序列化白名单
限制:
ObjectInputStream.resolveClass()
只允许安全类
✅ 3. 禁用原生反序列化
改用:
-
JSON
-
Protobuf
-
Kryo(安全模式)
✅ 4. 使用安全框架
-
Spring Security
-
Jackson safe typing
✅ 5. WAF / RASP
实时检测:
-
异常序列化流
-
Gadget特征
🧠 五、本质思考(高级认知)
这些漏洞的根本问题不是“代码写错”,而是:
❌ Java设计允许“数据驱动执行”
典型危险设计:
-
反射
-
动态代理
-
类加载
-
回调机制
📌 终极一句话总结:
不是漏洞链强,而是Java对象模型太“信任输入”
🚀 六、进阶思考
如果你已经看到这里,可以开始思考:
-
如何自动挖掘 Gadget?
-
如何构建自己的利用链?
-
如何做链级检测(而不是特征检测)?
🎯 结语
掌握 CC1~CC7,不只是“会打漏洞”,更重要的是:
👉 理解 Java 安全设计的边界
这才是你走向:
🧠 高级安全研究员
⚔️ 红队专家
🛡️ 漏洞分析师
的关键一步。
💬 互动
你可以在评论区聊聊:
-
哪条链你觉得最优雅?
-
有没有你自己挖到的 Gadget?
-
你觉得未来防御的方向是什么?
我们一起把这块领域吃透。🚀
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:AlphaNet Сяо Яо Сяо Яо《第109天-深度解析Java反序列化:揭秘Commons Collections五大Gadget Chain》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论