Skip to content

Latest commit

 

History

History
64 lines (54 loc) · 4.77 KB

File metadata and controls

64 lines (54 loc) · 4.77 KB

HutoolSimpleDSFactory(HutoolSimpleDSFactory)

  • 类别:javanative 别名:— 优先级:—
  • 作者:Unam4
  • 依赖cn.hutool.hutool-all:5.8.29

作用

构造一个 Hutool 的 SimpleDSFactory 数据源工厂对象,当其 getDataSource getter 在反序列化 / JSON 反序列化过程中被触发时,创建一个内含攻击者 JDBC URL 的 SimpleDataSource,把整条链桥接到 JDBC 攻击(JdbcUrlChains)。属于「Getter → JDBC」跳板构件。

链接标签

  • 入口 tagsDataSourceChainsGetterNotForCommonsBeanutilsNotForRome —— 本 gadget 本身是一个「可被 getter 触发的数据源」;Getter 表示它需由上游的 getter 触发型 gadget 承接;NotForCommonsBeanutils / NotForRome 是排他标记,声明本链不能被 CommonsBeanutils 链和 Rome 链驱动(原因见下)。
  • 衔接 nextTagsJdbcUrlChains —— 之后必须接一个提供恶意 JDBC URL 的 gadget(如 H2JavaJdbc1MysqlJdbc 等 JDBC sink),由 chain.doCreate 产出该 URL 字符串。
  • excludes:无。

源码剖析

核心逻辑集中在 getObjectinvoke 两个方法:

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);
}

invokechain.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)

本类无 @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 等。