Fastjson 1.2.83 漏洞复现与源码分析笔记

Fastjson 1.2.83 漏洞复现与源码分析笔记

研究方向:Java 反序列化、AutoType、动态类型加载、反射机制
环境:CentOS + JDK + Fastjson 1.2.83
目标:理解 Fastjson AutoType 工作机制以及 CVE 分析方法


1. Fastjson 简介

Fastjson 是阿里巴巴开源的 Java JSON 序列化与反序列化框架。

主要功能:

  • Java对象序列化为JSON
  • JSON反序列化为Java对象

普通反序列化:

User user = JSON.parseObject(json, User.class);

程序提前知道目标类型:

JSON
 |
 v
User.class
 |
 v
User对象

但是在复杂场景中,例如多态:

Animal animal = JSON.parseObject(json, Animal.class);

实际类型可能是:

Dog
Cat
Bird

因此 Fastjson 引入了:

AutoType

机制。


2. AutoType机制

2.1 @type指定Java类型

Fastjson支持:

{
    "@type":"java.util.Date"
}

其中:

@type

表示:

告诉 Fastjson:

我要创建哪个 Java 类。

解析流程:

JSON输入

    |
    v

读取 @type

    |
    v

得到类名字符串

    |
    v

ClassLoader加载Class

    |
    v

反射创建对象

    |
    v

Java对象

3. 实验环境搭建

3.1 创建目录

mkdir fastjson-lab

cd fastjson-lab

目录:

fastjson-lab

├── lib
│
├── src
│
└── FastjsonDemo.java

3.2 下载Fastjson 1.2.83

wget https://repo1.maven.org/maven2/com/alibaba/fastjson/1.2.83/fastjson-1.2.83.jar

复制:

cp fastjson-1.2.83.jar lib/

检查:

ls -lh lib/

结果:

fastjson-1.2.83.jar

4. Fastjson源码位置

源码:

fastjson-1.2.83/

核心文件:

ParserConfig.java

DefaultJSONParser.java

ThrowableDeserializer.java

TypeUtils.java

5. Fastjson解析入口

调用:

JSON.parse()

源码流程:

JSON.parse()

      |
      v

DefaultJSONParser

      |
      v

JavaBeanDeserializer

      |
      v

checkAutoType()

      |
      v

TypeUtils.loadClass()

      |
      v

反射创建对象


6. 动态类型加载分析

6.1 什么是动态类型加载

Java正常方式:

User user = new User();

编译阶段已经确定:

User.class

动态加载:

String className="java.util.Date";

Class clazz =
Class.forName(className);

运行期间:

字符串

java.util.Date

      |
      v

ClassLoader

      |
      v

Date.class

这就是:

Dynamic Class Loading

动态类型加载

7. Fastjson中的动态加载

核心代码:

文件:

ParserConfig.java

函数:

public Class<?> checkAutoType(
        String typeName,
        Class<?> expectClass,
        int features
)

作用:

根据字符串加载Java类。

例如:

输入:

java.lang.Exception

执行:

clazz = TypeUtils.loadClass(
        typeName,
        defaultClassLoader,
        true
);

等价理解:

Class.forName(
"java.lang.Exception"
);

最终:

java.lang.Exception

        |

        v

Exception.class

8. 反射实例化分析

动态加载之后:

得到:

Exception.class

注意:

Class对象
≠
Java对象

例如:

Class clazz = Exception.class;

此时内存:

Class对象

Exception.class

并没有:

Exception实例

需要创建:

new Exception();

但是:

Fastjson不知道具体类型。

所以使用:

Java Reflection
Java反射

9. Java反射机制

普通创建:

Exception e =
new Exception("hello");

反射:

Constructor c =
clazz.getConstructor(String.class);


Object obj =
c.newInstance("hello");

流程:

Class对象

      |

      v

寻找Constructor

      |

      v

调用newInstance()

      |

      v

创建对象

10. ThrowableDeserializer源码分析

文件:

fastjson-1.2.83/src/main/java/com/alibaba/fastjson/parser/deserializer/ThrowableDeserializer.java

核心代码:

String exClassName = lexer.stringVal();

exClass =
parser.getConfig()
.checkAutoType(
        exClassName,
        Throwable.class,
        lexer.getFeatures()
);

作用:

从JSON中获取异常类:

例如:

java.lang.Exception

然后:

checkAutoType()

        |

        v

Exception.class

11. 反射创建对象源码

调用:

ex = createException(
        message,
        cause,
        exClass
);

进入:

createException()

遍历构造方法:

for(Constructor<?> constructor :
        exClass.getConstructors())

寻找:

无参:

Exception()

单参数:

Exception(String)

双参数:

Exception(String,Throwable)

最终:

causeConstructor.newInstance(
        message,
        cause
);

完成:

Class对象

      |

      v

Constructor

      |

      v

newInstance()

      |

      v

Java对象

12. Fastjson完整调用链

JSON输入

{
 "@type":"java.lang.Exception"
}


        |

        v


DefaultJSONParser


        |

        v


ParserConfig.checkAutoType()


        |

        v


TypeUtils.loadClass()


        |

        v


Exception.class


        |

        v


Constructor.newInstance()


        |

        v


Exception对象


13. 漏洞核心原理

危险组合:

用户可控输入

        +

动态类加载

        +

反射实例化

攻击链:

用户输入

    |

    v

控制类名

    |

    v

ClassLoader加载类

    |

    v

反射调用构造函数

    |

    v

执行危险逻辑


14. Fastjson防护机制分析

14.1 denyHashCodes

黑名单:

denyHashCodes

作用:

禁止危险类加载。


14.2 acceptHashCodes

白名单:

acceptHashCodes

允许安全类。


14.3 SafeMode

源码:

if(safeMode){

throw new JSONException(
"safeMode not support autoType"
);

}

作用:

关闭AutoType。


15. CVE漏洞分析方法

研究Java框架时重点搜索:

类加载

关键词:

Class.forName

loadClass

checkAutoType

deserialize

反射调用

关键词:

newInstance

Constructor

invoke

Method.invoke

输入入口

寻找:

JSON

XML

YAML

ObjectInputStream


16. CVE分析思路

完整漏洞链:

输入点

  |

  v

数据流

  |

  v

危险函数

  |

  v

权限边界

  |

  v

漏洞影响

Fastjson:

输入:

@type


↓

处理:

checkAutoType()


↓

危险:

loadClass()


↓

执行:

Constructor.newInstance()


17. 本次实验总结

通过 Fastjson 1.2.83 源码分析,理解:

动态类型加载

定义:

程序运行期间,根据字符串加载Java类。

流程:

类名字符串

      |

      v

ClassLoader

      |

      v

Class对象


反射实例化

定义:

根据Class对象动态调用构造函数创建对象。

流程:

Class对象

      |

      v

Constructor

      |

      v

newInstance()

      |

      v

对象实例

Fastjson AutoType风险本质

不可信输入

      +

动态类加载

      +

反射执行

      =

反序列化安全风险

18. 后续研究方向

继续分析:

ParserConfig

        |

        v

denyHashCodes

        |

        v

acceptHashCodes

        |

        v

TypeUtils.loadClass()

重点研究:

  • CVE-2017-18349
  • CVE-2019-6443
  • CVE-2022-25845
  • Fastjson AutoType绕过
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值