一、Gadget链基础概念
1.1 什么是Gadget链?
Gadget链是由一系列看似无害的类和方法组成的调用链,当这些组件以特定方式组合时,可以被攻击者利用来执行恶意操作。在Java反序列化漏洞中,Gadget链通常指从readObject()方法开始,到危险方法(如Runtime.exec())结束的一系列方法调用。
Gadget链三要素:
-
触发点(Source):反序列化入口(如
ObjectInputStream.readObject()) -
传递链(Gadgets):中间方法调用
-
执行点(Sink):危险操作(如命令执行、文件操作)
1.2 基本概念
-
Gadget(代码片段):指程序中已有的短小指令序列,通常以ret指令结尾
-
Gadget链:将多个gadget按特定顺序组合,实现攻击者预期的复杂操作
1.3 技术原理
自动化挖掘技术通常包括以下步骤:
-
Gadget发现:通过静态分析或动态分析识别程序中的所有可用gadget
-
Gadget分类:根据功能(如内存读写、算术运算、控制流转移等)对gadget进行分类
-
约束求解:使用符号执行或约束求解器分析gadget间的数据流和控制流关系
-
链构建:自动组合gadget形成有效攻击链,满足特定攻击目标
1.4 主要方法
-
基于符号执行的方法:使用符号执行探索程序路径,识别有用的gadget组合
-
基于约束求解的方法:将gadget链构建问题转化为约束求解问题
-
启发式搜索方法:使用遗传算法等启发式方法搜索有效的gadget组合
-
机器学习方法:利用机器学习模型预测有效的gadget组合
1.5 应用场景
-
面向返回编程(ROP)攻击
-
面向跳转编程(JOP)攻击
-
二进制漏洞利用自动化
-
软件安全加固(通过识别潜在可利用的gadget)
1.6 代表性工具
-
ROPgadget
-
angrop(基于angr框架)
-
Q(基于二进制分析平台)
-
AUTOEXP(自动化漏洞利用生成工具)
这项技术显著提高了漏洞利用的自动化程度,同时也促使防御技术(如ASLR、CFG等)的发展。
1.7 典型Gadget链示例
以经典的Apache Commons Collections链为例:
// 恶意序列化数据利用链
ObjectInputStream.readObject()
-> AnnotationInvocationHandler.readObject()
-> Map(Proxy).entrySet()
-> AnnotationInvocationHandler.invoke()
-> LazyMap.get()
-> ChainedTransformer.transform()
-> InvokerTransformer.transform()
-> Runtime.exec()
调用链分析:
-
反序列化触发
AnnotationInvocationHandler.readObject() -
通过动态代理调用
invoke方法 -
LazyMap触发Transformer链 -
InvokerTransformer反射调用危险方法
二、Gadget链自动化挖掘技术
2.1 传统挖掘方法的局限性
传统Gadget链挖掘面临两大挑战:
-
静态路径爆炸:Java多态特性导致调用图过于庞大
-
对象约束复杂:有效Payload需要满足特定字段条件
2.2 现代挖掘技术突破
复旦大学提出的JDD框架通过创新方法解决了这些问题:
技术亮点:
-
自底向上的链组合:
-
将完整链拆分为以动态调用为边界的片段
-
组合片段形成完整利用链
-
-
注入对象约束求解:
// 约束示例:字段A必须非空且字段B为特定值 if (fieldA != null && "danger".equals(fieldB)) { executeMaliciousCode(); } -
实验成果:
-
在Ysoserial基准上发现91条新链
-
静态分析误报率降至0%
-
检测到fastjson2等组件的新漏洞
-
三、常见Gadget链分析
3.1 JDK内置链
HashSet触发链:
ObjectInputStream.readObject()
-> HashSet.readObject()
-> HashMap.put()
-> TiedMapEntry.hashCode()
-> LazyMap.get()
-> ChainedTransformer.transform()
特点:利用JDK集合类的标准方法触发
3.2 第三方库链
Groovy链:
ObjectInputStream.readObject()
-> MethodClosure.readObject()
-> doCall()
-> Method.invoke()
-> ProcessBuilder.start()
特点:利用Groovy的方法闭包特性
四、防御策略与实践
4.1 输入过滤
白名单验证示例:
public class SafeObjectInputStream extends ObjectInputStream {
private static final Set<String> ALLOWED_CLASSES =
Set.of("java.lang.String", "java.util.Date");
@Override
protected Class<?> resolveClass(ObjectStreamClass desc)
throws IOException, ClassNotFoundException {
if (!ALLOWED_CLASSES.contains(desc.getName())) {
throw new InvalidClassException("Unauthorized class");
}
return super.resolveClass(desc);
}
}
4.2 运行时防护
Java Agent检测:
public class DangerousMethodAgent {
public static void premain(String args, Instrumentation inst) {
inst.addTransformer((loader, className, classBeingRedefined,
protectionDomain, classfileBuffer) -> {
if (className.contains("InvokerTransformer")) {
throw new SecurityException("Dangerous class detected");
}
return classfileBuffer;
});
}
}
2114

被折叠的 条评论
为什么被折叠?



