前言
关于Jackson的介绍和用法,王网上已经有很多全面的文章进行分析讲解,不做过多的赘述了,参考下列文章即可。
https://www.cnblogs.com/LittleHann/p/17811918.html#_lab2_3_0
对于setter、getter调用逻辑的思考
上述文章中对于Jackson反序列化调用setter
、getter
方法的描述过于冗杂且不清晰,故想用自己的话和理解重新写一下。
在com.fasterxml.jackson.databind.deser.BeanDeserializer#vanillaDeserialize
中,会根据属性从this._beanProperties
寻找对应的调用方法
调用setter/getter
,在com.fasterxml.jackson.databind.deser.BeanDeserializerFactory#addBeanProps
中可以看到对应逻辑
(1) 首先看是否有setter方法,若有则调用setter
(2) 若没有setter方法,其次查看有无这个子段
条件 | 结果 |
---|---|
字段访问属性为public,无getter方法 | 根据字段反射赋值,正常反序列化 |
字段访问属性为private,有public getter方法 | 正常反序列化 |
字段访问属性为private,无getter/有private getter方法 | 无法正常反序列化 |
(3) 若setter
和字段都没有,最后调用public getter
方法,前提是getter方法的返回值必须是Collection
、Map
以及它们的字类
其实这就顺带解释了CVE-2017-7525 (基于TemplatesImpl
的Jackson反序列化利用链)为什么能触发getOutProperties
方法,因为TemplatesImpl
类中既没有setOutProperties
方法也没有outProperties
字段,且getOutProperties
的返回值Properties
类是Map
的字类。
CVE-2017-7525 (TemplatesImpl链)
影响版本
Jackson 2.6系列 < 2.6.7.1
Jackson 2.7系列 < 2.7.9.1
Jackson 2.8系列 < 2.8.8.1
JDK < jdk7u80
EXP
1 | { |
可以注意到与Fastjson_Templates
利用链的不同点,Jackson使用了transletBytecodes
和transletName
替换了_bytecodes
和_name
,因为jackson反序列化需要调用它们的setter
方法进行赋值
JDK版本限制
为什么JDK7u13
可以,JDK7u80
不行呢,原因是对_tfactory
参数的处理
在com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl#defineTransletClasses
中,加载恶意字节码之前会走进一个其它的逻辑
可以看到JDK7u13
中没有调用_tafactory
,而JDK7u80
调用了_tfactory
_tfactory
在TemplatesImpl
类中的默认值为null
,调用null
的方法会报错空指针异常
且_tfactory
字段的访问属性为private
,且无setter/getter
方法,导致无法在Jackson反序列化的过程中被赋值
修复
在com.fasterxml.jackson.databind.deser.BeanDeserializerFactory
引入黑名单
在创建反序列化器的时候,调用到com.fasterxml.jackson.databind.deser.BeanDeserializerFactory#createBeanDeserializer
时会调用checkIllegalTypes
方法,进行黑名单检测
提取类名在黑名单中找,若在黑名单中直接抛出异常
1 | Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Illegal type (com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl) to deserialize: prevented for security reasons |