fastjson漏洞总结
介绍
fastjson是一个由阿里开发的一个开源Java类库,可以将Java对象转换为JSON格式(序列化),当然它也可以将JSON字符串转换为Java对象(反序列化)Fastjson 可以操作任何Java对象,即使是一些预先存在的没有源码的对象,使用还是比较广泛的
那什么是json?
json本质就是一种字符串,用于信息的存储和交换。json全称是JavaScript object notation,即JavaScript对象标记法,使用键值对进行信息的存储,举个简单的例子如下
1 | |
相关概念
在进行fastjson的漏洞复现学习之前需要了解几个概念
JNDI
JNDI是一组应用程序接口,提供了查找和访问命名和目录服务的通用、统一的接口,用于定位网络、用户、对象和服务等资源,是J2EE规范中是重要的规范之一,JNDI底层支持RMI远程对象,JNDI接口可以访问和调用RMI注册过的服务,JNDI根据名字动态加载数据,支持的服务有DNS、LDAP、CORBA、RMI
JNDI注入
简单来说,JNDI接口在初始化时,可以将RMI URL作为参数传入,而JNDI注入就出现在客户端的lookup()函数中,如果lookup()的参数可控就可能被攻击,例如
1 | |
RMI
RMI服务端可以通过References类来绑定一个外部的远程对象,当RMI绑定了References之后,首先会利用Referenceable.getReference()获取绑定对象的引用,并且在目录中保存,当客户端使用lookup获取对应名字的时候,会返回ReferenceWrapper类的代理文件,然后会调用getReference()获取Reference类,最终通过factory类将Reference转换为具体的对象实例
任何可以被远程调用方法的对象必须实现 java.rmi.Remote接口,远程对象的实现类必须继承UnicastRemoteObject类,如果不继承UnicastRemoteObject类,则需要手工初始化远程对象,在远程对象的构造方法的调用UnicastRemoteObject.exportObject()静态方法,例如
1 | |
fastjson反序列化漏洞原理
fastjson的漏洞本质还是一个java的反序列化漏洞,由于引进了AutoType功能,fastjson在对json字符串反序列化的时候,会读取到@type的内容,将json内容反序列化为java对象并调用这个类的setter方法,fastjson引入了AutoType,即在序列化的时候,先把原始类型记录下来。使用@type的键记录原始类型
使用autotype处理Json对象的时候,如果未对@type字段进行完整的安全性验证,攻击者可以传入危险类,并调用危险类连接远程RMI主机,通过其中的恶意类执行代码,攻击者通过这种方式可以实现远程代码执行漏洞,获取服务器敏感信息,甚至可以利用此漏洞进一步的对服务器数据进行操作。说白了就是,FastJson在解析json的过程中,支持使用@type字段来指定反序列化的类型,并调用该类的set或get方法来访问属性,当组件开启了autotype功能并且反序列化不可信数据时,攻击者可以构造数据,从而进行进一步的利用,我用ppt大概做一个流程图
漏洞复现
1.2.24
我这里用docker搭建复现环境
1.2.24是没有任何fastjson特征,我们构造数据包,用POST请求,并且加上Content-Type: application/json,发包可以证实 啥特征没有
首先编译恶意类代码,我们以在/tmp目录下创建一个successFrank文件为复现成功标志:
1 | |
然后用javac编译成class文件,然后在当前目录用python启动一个http服务,这个时候就用到我们的marshalsec,启动一个RMI服务器,设置监听端口,并制定加载远程的恶意类
(marshalsec下载地址:https://github.com/mbechler/marshalsec.git)
(需要手动maven编译成jar包)
1 | |
随后抓包,同样使用POST请求,并且加上Content-Type,在最后输入payload
1 | |
发送数据包
检测一下是否在tmp目录touch创建了文件successFrank即可,success!
dnslog回显
创建一个恶意类,执行ping命令
1 | |
步骤同上,修改完数据包之后,放包 成功回显
1.2.47
在47版本中最明显的点就是json报错会出现fastjson特征
dnslog回显
构造数据包
1 | |
反弹shell