改造gadgetinspector篇-自动化挖掘Fastjson gadget chain
字数 1202 2025-08-25 22:58:55
Fastjson反序列化利用链自动化挖掘工具改造指南
0x01 前言
本文基于对gadgetinspector工具的改造,使其能够自动化挖掘Fastjson反序列化利用链。gadgetinspector是一款Java反序列化利用链自动挖掘工具,但原版存在一些局限性:
- 对于运行时确定的实现(多态性)无法进行准确的污点分析
- 调用链搜索不完整,同样由于多态性问题
- 缺少JNDI lookup的sink判断
- 不支持Fastjson利用链挖掘
0x02 添加新序列化方式的基础架构
gadgetinspector通过GIConfig接口支持多种反序列化方式的扩展,需要实现三个核心组件:
1. SerializableDecider(序列化决策者)
判断目标类是否可被反序列化
2. ImplementationFinder(实现查找器)
对于接口方法,判断其实现类是否可被反序列化
3. SourceDiscovery(源发现)
搜索整个gadget chain的入口点(触发方法)
以Jackson为例的实现:
public class JacksonDeserializationConfig implements GIConfig {
@Override
public String getName() { return "jackson"; }
@Override
public SerializableDecider getSerializableDecider(...) {
return new JacksonSerializableDecider(methodMap);
}
@Override
public ImplementationFinder getImplementationFinder(...) {
return new JacksonImplementationFinder(getSerializableDecider(...));
}
@Override
public SourceDiscovery getSourceDiscovery() {
return new JacksonSourceDiscovery();
}
}
0x03 Fastjson特性分析
可被反序列化的类特征
Fastjson反序列化时:
- 优先使用无参构造方法实例化
- 若无无参构造方法,则选择参数类型与自身一致的单参构造方法
- 若以上都不存在,会遍历构造方法取最后一个(但需要autoType支持)
- 通过
TypeUtils.loadClass加载的类会被缓存,可绕过后续检查
结论:Fastjson理论上可以反序列化任何类,无论是否存在无参构造方法。
反序列化可触发执行的方法特征
Setter方法:
- 方法名长度大于3
- 非静态方法
- 返回类型为void或自身class类型
- 显式入参只有一个
Getter方法:
- 对应setter不存在
- 方法名长度大于3且第4个字符大写
- 非静态方法
- 无入参
- 返回值类型是Collection/Map/AtomicBoolean/AtomicInteger/AtomicLong或其子类
0x04 Fastjson三件套实现
1. FastjsonSerializableDecider
public class FastjsonSerializableDecider implements SerializableDecider {
@Override
public Boolean apply(ClassReference.Handle handle) {
return Boolean.TRUE; // Fastjson几乎可以反序列化任何类
}
}
2. FastjsonSourceDiscovery
public class FastjsonSourceDiscovery extends SourceDiscovery {
@Override
public void discover(...) {
for (MethodReference.Handle method : methodMap.keySet()) {
// Getter方法判断
if (method.getName().startsWith("get")
&& method.getDesc().startsWith("()")) {
// 检查返回值类型等条件
addDiscoveredSource(new Source(method, 0));
}
// Setter方法判断
if (method.getName().startsWith("set")
&& method.getDesc().matches("\\(L[V")) {
addDiscoveredSource(new Source(method, 1));
}
}
}
}
3. FastjsonImplementationFinder
public class FastjsonImplementationFinder implements ImplementationFinder {
@Override
public Set<MethodReference.Handle> getImplementations(MethodReference.Handle target) {
Set<MethodReference.Handle> allImpls = new HashSet<>();
allImpls.add(target); // 直接添加目标方法
return allImpls;
}
}
4. 配置集成
public class FastjsonDeserializationConfig implements GIConfig {
@Override public String getName() { return "fastjson"; }
@Override public SerializableDecider getSerializableDecider(...) {
return new FastjsonSerializableDecider(methodMap);
}
@Override public ImplementationFinder getImplementationFinder(...) {
return new FastjsonImplementationFinder(getSerializableDecider(...));
}
@Override public SourceDiscovery getSourceDiscovery() {
return new FastjsonSourceDiscovery();
}
}
0x05 优化Sink判断 - 加入JNDI lookup
在GadgetChainDiscovery.isSink方法中添加:
if (inheritanceMap.isSubclassOf(method.getClassReference(),
new ClassReference.Handle("javax/naming/Context"))
&& method.getName().equals("lookup")) {
return true;
}
0x06 测试效果
以HikariCP-3.4.1.jar测试,成功挖掘到以下利用链:
com/zaxxer/hikari/HikariConfig.setMetricRegistry(Ljava/lang/Object;)V (1)
com/zaxxer/hikari/HikariConfig.getObjectOrPerformJndiLookup(Ljava/lang/Object;)Ljava/lang/Object; (1)
javax/naming/InitialContext.lookup(Ljava/lang/String;)Ljava/lang/Object; (1)
总结
通过改造gadgetinspector,我们实现了:
- Fastjson反序列化链的自动化挖掘
- JNDI lookup sink的识别
- 完整的Fastjson特性支持
这种改造方法同样适用于其他反序列化框架的扩展,只需根据目标框架的特性调整三件套的实现逻辑即可。