某json<=1.2.68 Autotype bypass
2021-05-06 10:54:07 Author: xz.aliyun.com(查看原文) 阅读量:155 收藏

文章前言

本篇文章主要对FastJSON AutoType的校验原理,以及绕过方式进行简单的分析介绍,跟多的是学习记录,文章涉及的绕过方式都是"站在巨人的肩膀上"看风景的,很后悔当初去看了Jackson-databind而丢弃了fastJSON,哎....,悔不当初呀~

校验原理

FastJSON中的checkAutoType()函数用于对反序列化的类进行黑白名单校验,我们首先来看一下checkAutoType()函数的检查流程:
代码位置:fastjson-1.2.68\src\main\java\com\alibaba\fastjson\parser\ParserConfig.java
checkAutoType函数默认需要传递三个参数:
String typeName:被序列化的类名
Class<?> expectClass:期望类()
int features:配置的feature值
这里的expectClass(期望类)的目的是为了让一些实现了expectClass这个接口的类可以被反序列化,可以看到这里首先校验了typeName是否为空、autoTypeCheckHandlers是否为null,之后检查safeMode模式是否开启(在1.2.68中首次出现,配置safeMode后,无论白名单和黑名单都不支持autoType)、typeName的长度来决定是否开启AutoType:

public Class<?> checkAutoType(String typeName, Class<?> expectClass, int features) {
        if (typeName == null) {
            return null;
        }

        if (autoTypeCheckHandlers != null) {
            for (AutoTypeCheckHandler h : autoTypeCheckHandlers) {
                Class<?> type = h.handler(typeName, expectClass, features);
                if (type != null) {
                    return type;
                }
            }
        }

        final int safeModeMask = Feature.SafeMode.mask;
        boolean safeMode = this.safeMode
                || (features & safeModeMask) != 0
                || (JSON.DEFAULT_PARSER_FEATURE & safeModeMask) != 0;
        if (safeMode) {
            throw new JSONException("safeMode not support autoType : " + typeName);
        }

        if (typeName.length() >= 192 || typeName.length() < 3) {
            throw new JSONException("autoType is not support. " + typeName);
        }

然后判断期望类expectClass,从下面可以看到这里的Object、Serializable、Cloneable、Closeable、EventListener、Iterable、Collection都不能作为期望类:

final boolean expectClassFlag;
        if (expectClass == null) {
            expectClassFlag = false;
        } else {
            if (expectClass == Object.class
                    || expectClass == Serializable.class
                    || expectClass == Cloneable.class
                    || expectClass == Closeable.class
                    || expectClass == EventListener.class
                    || expectClass == Iterable.class
                    || expectClass == Collection.class
                    ) {
                expectClassFlag = false;
            } else {
                expectClassFlag = true;
            }
        }

之后从typeName中解析出className,然后计算hash进行内部白名单、黑名单匹配,之后如果不在白名单内且未开启AutoType或者expectClassFlag为true则进行hash校验——白名单acceptHashCodes、黑名单denyHashCodes,如果在白名单内就加载,在黑名单中就抛出异常:

String className = typeName.replace('$', '.');
        Class<?> clazz;

        final long BASIC = 0xcbf29ce484222325L;
        final long PRIME = 0x100000001b3L;

        final long h1 = (BASIC ^ className.charAt(0)) * PRIME;
        if (h1 == 0xaf64164c86024f1aL) { // [
            throw new JSONException("autoType is not support. " + typeName);
        }

        if ((h1 ^ className.charAt(className.length() - 1)) * PRIME == 0x9198507b5af98f0L) {
            throw new 

文章来源: http://xz.aliyun.com/t/9476
如有侵权请联系:admin#unsafe.sh