- 类别:javanative 别名:— 优先级:—
- 作者:Unam4
- 依赖:
cn.hutool.hutool-all:5.8.29
构造一个 Hutool 的 SimpleDSFactory 数据源工厂对象,当其 getDataSource getter 在反序列化 / JSON 反序列化过程中被触发时,创建一个内含攻击者 JDBC URL 的 SimpleDataSource,把整条链桥接到 JDBC 攻击(JdbcUrlChains)。属于「Getter → JDBC」跳板构件。
- 入口
tags:DataSourceChains、Getter、NotForCommonsBeanutils、NotForRome—— 本 gadget 本身是一个「可被 getter 触发的数据源」;Getter表示它需由上游的 getter 触发型 gadget 承接;NotForCommonsBeanutils/NotForRome是排他标记,声明本链不能被 CommonsBeanutils 链和 Rome 链驱动(原因见下)。 - 衔接
nextTags:JdbcUrlChains—— 之后必须接一个提供恶意 JDBC URL 的 gadget(如H2JavaJdbc1、MysqlJdbc等 JDBC sink),由chain.doCreate产出该 URL 字符串。 excludes:无。
核心逻辑集中在 getObject 与 invoke 两个方法:
public Object getObject(String JDBC_URL) {
Setting setting = new Setting();
setting.setCharset(null);
setting.set("url", JDBC_URL);
setting.set("initialSize", "1");
SimpleDSFactory simpleDSFactory = new SimpleDSFactory(setting);
return simpleDSFactory;
}getObject 用 Hutool 的 Setting(配置容器)填入 url(攻击者可控的 JDBC URL)和 initialSize=1,据此构造 cn.hutool.db.ds.simple.SimpleDSFactory。注意此刻仅仅是创建工厂对象,尚未建立数据库连接——真正的连接发生在后续 getDataSource → getConnection 被调用时。
@Override
public Object invoke(GadgetContext context, GadgetChain chain) throws Exception {
String jdbcUrl = (String)chain.doCreate(context);
context.put(ContextTag.SUPER_CLASS_NAME_KEY, DSFactory.class);
context.put(ContextTag.SPECIAL_METHOD_NAME_KEY, "getDataSource");
context.put(ContextTag.GETTER_PARAM_NAME_KEY, "dataSource");
return this.getObject(jdbcUrl);
}invoke 先 chain.doCreate(context) 取得内层 gadget 产出的 JDBC URL 字符串,再向 GadgetContext 注入三条关键信息,供上游的 getter 触发型 gadget 读取:
SUPER_CLASS_NAME_KEY = DSFactory.class:告知上游序列化时应以父类cn.hutool.db.ds.DSFactory的类型来描述本对象(这样才能找到getDataSource属性描述符);SPECIAL_METHOD_NAME_KEY = "getDataSource":要触发的目标 getter 方法名;GETTER_PARAM_NAME_KEY = "dataSource":对应的 property 名。
触发条件与排他原因(对应 description):类字段固定 getterMethodName="getDataSource"、getterPropertyName="dataSource"。当 getDataSource() 被调用时,Hutool 内部会 new 出一个 SimpleDataSource 并最终触发 getConnection,用恶意 URL 连接数据库,从而进入 JDBC 攻击面。
- 无法用于 CB(CommonsBeanutils)链:CB 链只针对单个指定 property 触发一次 getter,而
getDataSource只是创建SimpleDataSource对象、其创建过程本身不会触发getConnection,故打不通。 - 无法用于 Rome 链:Rome 依赖
ToStringBean通过 introspection 获取 property 描述,但获取不到DSFactory.class的 property 描述符,无法触发getDataSource。 - 适用 Jackson / Fastjson 等 JSON 反序列化:这类序列化会对 property 多次触发 getter/setter,从而经 setter 路径触发
getConnection。但 Jackson 的 getter 触发顺序带随机性,存在不稳定问题。
本类无 @Param。恶意 JDBC URL 由下游 JdbcUrlChains gadget 提供,getterMethodName / getterPropertyName 为写死的私有常量。
- 依赖
cn.hutool.hutool-all:5.8.29(Hutool 全量包)。 - 核心 sink:
cn.hutool.db.ds.pooled.SimpleDataSource#getDataSource。 - 只在「会主动调用 getter 且能沿 setter 触发 getConnection」的场景(Jackson/Fastjson)稳定;CB / Rome 场景不可用(见上)。
- 最终危害取决于所接 JDBC sink,可为 H2/MySQL 等的 RCE 或文件读取。
自由构件,未直接出现在预设链(usedInChains 为空)。可与 Fastjson / Jackson 入口 + JDBC sink 手工组合。
- 上游(触发者):Fastjson、Jackson 等具备
Getter触发能力的入口 gadget。 - 下游(
nextTags=JdbcUrlChains):H2JavaJdbc1、MysqlJdbc、H2JavaExecJdbc1 等 JDBC sink。 - 同族:其他数据源工厂型跳板 HutoolJndiDSFactory、HutoolPooledDSFactory、DruidDataSource、C3p0DataSource 等。