参考文章

  1. csdn-CC链总结
  2. 博客园-Java反序列化Commons-Collection篇01-CC1链
  3. freebuf-Java安全 CC链1分析
  4. 个人博客-Java Web学习
  5. 先知社区-通俗易懂的Java Commons Collection 2分析
  6. 博客园-1vxyz-随笔分类-Java安全

介绍

Apache Commons Collections 是一个为 Java 提供扩展集合类的开源项目, 它提供了一系列有用的集合类和算法, 可以使编程变得更加简单, 快捷和高效

CC链(Commons Collections反序列化漏洞利用链)是Java安全领域中最具代表性的反序列化攻击技术之一, 其核心通过恶意构造的序列化对象触发Apache Commons Collections库中的反射机制, 最终实现任意代码执行

环境准备

JDK版本: CC1、CC3、CC5、CC6、CC7 建议使用JDK 8u65或更低版本 JDK 8u71后修复了AnnotationInvocationHandler的触发逻辑

Commons Collections版本: CC1-CC3、CC5-CC7 使用 3.2.1;CC2、CC4 使用 4.0 注意:3.2.2/4.1版本增加了安全限制,但若启用不安全序列化属性仍可能存在风险

工具:推荐使用ysoserial生成Payload进行测试

CC1可以看Java安全 CC链1分析的第一部分来配置IDEA和java 8u66(我用这个版本进行复现)

CC2可以看先知社区-通俗易懂的Java Commons Collection 2分析配置IDEA环境

前置知识

CC链

流程图总览CC利用链.excalidraw

CC1 TransformedMap

入口: AnnotationInvocationHandler#readObject 核心组件: TransformedMap 条件: jdk 1.7限制

ObjectInputStream.readObject()
AnnotationInvocationHandler.readObject()
memberValues.entrySet().iterator().next().setValue()
TransformedMap.checkSetValue()
ChainedTransformer.transform()
ConstantTransformer.transform() [获取Runtime类]
InvokerTransformer.transform() [反射获取getRuntime方法]
InvokerTransformer.transform() [反射调用getRuntime方法]
InvokerTransformer.transform() [反射调用exec方法执行命令]

CC1 LazyMap

入口: AnnotationInvocationHandler#readObject 核心组件: LazyMap 条件: jdk 1.7限制

ObjectInputStream.readObject()
AnnotationInvocationHandler.readObject()
memberValues.entrySet().iterator().next().getValue()
Proxy.invoke() [动态代理调用]
LazyMap.get()
factory.transform() [ChainedTransformer.transform()]
迭代调用链

CC2 PriorityQueue

入口: TransformingComparator#compare 核心组件: PriorityQueueTemplatesImpl 条件: jdk无限制, CommonsCollections4

ObjectInputStream.readObject()
PriorityQueue.readObject()
heapify()
siftDown()
siftDownUsingComparator()
TransformingComparator.compare()
InvokerTransformer.transform()
TemplatesImpl.newTransformer()
TemplatesImpl.getTransletInstance()
TransletClassLoader.defineClass() [加载恶意字节码]
恶意类的静态代码块/构造函数执行 [命令执行]

CC3 TrAXFilter

入口: AnnotationInvocationHandler#readObject 核心组件: TrAXFilterTemplatesImpl 条件: jdk1.7

ObjectInputStream.readObject()
AnnotationInvocationHandler.readObject()
memberValues.entrySet().iterator().next().getValue()
Proxy.invoke() [动态代理调用]
LazyMap.get()
factory.transform() [ChainedTransformer.transform()]
ConstantTransformer.transform() [获取TrAXFilter类]
InstantiateTransformer.transform()
TrAXFilter构造函数()
templates.newTransformer() [TemplatesImpl.newTransformer()]
TemplatesImpl.getTransletInstance()
TransletClassLoader.defineClass() [加载恶意字节码]
恶意类的静态代码块/构造函数执行 [命令执行]

别看很长, 其实是拼接CC1的lazyMap.get() -> InvokerTransformer.transform()

CC4 组合利用

入口: TransformingComparator#compare 核心组件: PriorityQueueTrAXFilter 条件: CommonsCollections4

ObjectInputStream.readObject()
PriorityQueue.readObject()
heapify()
siftDown()
siftDownUsingComparator()
TransformingComparator.compare()
ChainedTransformer.transform()
ConstantTransformer.transform() [获取TrAXFilter类]
InstantiateTransformer.transform()
TrAXFilter构造函数()
templates.newTransformer() [TemplatesImpl.newTransformer()]
TemplatesImpl.getTransletInstance()
TransletClassLoader.defineClass() [加载恶意字节码]
恶意类的静态代码块/构造函数执行 [命令执行]

结合CC2的PriorityQueue触发点和CC3的TrAXFilter利用方式

CC5 TiedMap

入口: BadAttributeValueExpException#readObject 核心组件: TiedMapEntryLazyMap 条件: 无任何要求,可以直接使用

ObjectInputStream.readObject()
BadAttributeValueExpException.readObject()
val.toString() [TiedMapEntry.toString()]
TiedMapEntry.getValue()
LazyMap.get()
factory.transform() [ChainedTransformer.transform()]
迭代调用链

CC6 hashCode

入口: HashMap#hash -> TiedMapEntry#hashCode 核心组件: TiedMapEntryHashMap 条件: 无任何要求,可以直接使用

ObjectInputStream.readObject()
HashSet.readObject()
HashMap.put()
HashMap.hash()
TiedMapEntry.hashCode()
TiedMapEntry.getValue()
LazyMap.get()
factory.transform() [ChainedTransformer.transform()]
迭代调用链

走urldns反序列化一套

CC7

入口: Hashtable#reconstitutionPut 核心组件: Hashtable

ObjectInputStream.readObject()
Hashtable.readObject()
Hashtable.reconstitutionPut()
AbstractMap.equals()
TiedMapEntry.equals()
TiedMapEntry.getValue()
LazyMap.get()
factory.transform() [ChainedTransformer.transform()]
迭代调用链

在CC6的基础上多走了一步 HashTable

关键链解析

CC3链-TrAXFilter与字节码加载

CC3链的核心目的是绕过一些安全规则对InvokerTransformer类的限制(例如黑名单)

它不再直接使用InvokerTransformer来调用方法,而是利用了TrAXFilter类; CC3链通过InstantiateTransformer来实例化TrAXFilter类,并传入恶意构造的TemplatesImpl对象,最终在实例化过程中触发TemplatesImpl#newTransformer(),加载并执行其中的恶意字节码; 这使得CC3链更侧重于类加载而非直接的命令执行

CC6链-hashCode的利用

CC6链提供了一种非常通用的触发方式; 它通过TiedMapEntry#hashCode()方法触发TiedMapEntry#getValue(), 进而调用LazyMap#get()和后续的Transformer

该链的触发点HashMap#hash()在反序列化读取数据时会被调用, 因此不受JDK版本限制, 适用性非常广泛

CC4链-组合利用

CC4链可以看作是CC2和CC3思想的结合; 它像CC2一样使用PriorityQueueTransformingComparator作为触发入口, 但像CC3一样使用InstantiateTransformer来实例化TrAXFilter并最终触发TemplatesImpl中的字节码, 从而避免使用可能被禁用的InvokerTransformer

绕过技术与历史修复

JDK版本的绕过

JDK 8u71+修复了AnnotationInvocationHandler#readObject的逻辑,导致直接依赖它的CC1链失效; 应对策略是寻找新的触发点, 如CC6利用HashMap#hashCode(), CC2/CC4利用PriorityQueue#readObject()中的比较器

Commons Collections的修复

在3.2.2和4.1版本中, 官方试图修复漏洞;

例如,在3.2.2版本中,对InvokerTransformerInstantiateTransformer等类的序列化支持增加了开关

这些开关默认情况下关闭,反序列化这些类会抛出UnsupportedOperationException异常; 若要启用,需设置系统属性org.apache.commons.collections.enableUnsafeSerialization=true

需要注意的是, 3.2.2版本的修复并不彻底, 因为它只是增加了一个默认关闭的开关, 如果应用程序在启动时启用了不安全的序列化属性, 仍然可能存在风险

其他

Commons Collections3和4的区别

Commons Collections 3和4是Java编程语言中的开源类库,用于提供更多的集合数据结构和工具类。它们的主要区别如下:

架构:Commons Collections 4使用了新的架构,通过更好的设计和实现,提高了性能和可用性。

功能:Commons Collections 4新增了一些功能,例如BloomFilter,MultiValuedMap等。

兼容性:Commons Collections 4支持Java 8和以上版本,而Commons Collections 3只支持Java 7及以下版本。

依赖:Commons Collections 4移除了对其他类库的依赖,例如BeanUtils和ComparatorUtils,这使得它更加轻便和易用。

Commons Collections 4是一个更为现代化和高效的Java集合类库,更适合使用Java 8及以上版本。但如果你仍然需要在Java 7及以下版本中使用,那么Commons Collections 3是一个不错的选择。

利用链的演变与绕过

JDK版本适配问题 JDK 8u71+修复了AnnotationInvocationHandler的触发逻辑,导致CC1链失效。

替代方案: CC3链:引入TemplatesImpl类,通过字节码加载执行命令。 CC6链:改用HashSet和HashMap的hashCode()触发点79。

Commons Collections的修复与绕过 官方修复(3.2.2+):在InvokerTransformer中增加序列化开关,默认关闭反序列化功能58。 绕过手段:使用其他危险类(如InstantiateTransformer)构造新链,或依赖未修复的4.x版本组件