基于 TemplatesImpl 利用链
0x01 影响版本
Jackson 2.6 系列 < 2.6.7.1
Jackson 2.7 系列 < 2.7.9.1
Jackson 2.8 系列 < 2.8.8.1
0x02 限制
由于是打的 TemplatesImpl 链,所以要求 JDK 版本是 7u21 或者 8u20,动态代理相关的链子,这部分之前已经分析过了
0x03 漏洞复现
Test.java
1 | public class Test { |
SimpleCalc. java
1 | public class SimpleCalc extends AbstractTranslet { |
PoC.java
1 | public class PoC { |
其实这里看完代码之后马上就有一个问题:Jackson 是调用任意的构造函数与任意的 setter 方法,为什么会触发这条链子呢?
7u21 这条链子本质上其实是 TemplateImpl 类的类动态加载,配合上动态代理来打的,可是这里不论是动态代理,还是 TemplatesImpl.getOutputProperties()
,都和 Jackson 没关系。所以这里可以说是非常疑惑了
0x04 漏洞分析
下断点调试
首先是第一次到 com.fasterxml.jackson.databind.deser.BeanDeserializer#deserialize
方法,反序列化 Test 类,会走到其构造函数里面,并且继续处理 object
继续往下,下一步是反序列化 object
里面的数据。
这里可以看到 _beanProperties
属性,其中包含了哪些呢?
1 | Properties=[uriresolver([simple type, class javax.xml.transform.URIResolver]), transletBytecodes([array type, component type: [array type, component type: [simple type, class byte %}]), stylesheetDOM([simple type, class com.sun.org.apache.xalan.internal.xsltc.DOM]), transletName([simple type, class java.lang.String]), outputProperties([map type; class java.util.Properties, [simple type, class java.lang.String] -> [simple type, class java.lang.String %})] |
除了 setter 函数中的属性之外,还有 outputProperties
,为什么 outputProperties
会被拿到呢?因为 outputProperties
属性有相应的 getter 方法,而其他属性却没有
接着来看看对于 outputProperties
是怎么处理的
outputProperties 属性在 deserializeAndSet()
函数中是通过反射机制调用它的 getter 方法,这就是该利用链能被成功触发的原因
这里也指出了一条攻击利用手法,也就是只要构造函数中存在的属性,不存在 setter 方法时,都会自动调到 getter 方法。
从而就能够利用成功了。
后续就是最基础的 TemplatesImpl 动态加载字节码的过程,不再展开了
0x05 其他细节
高版本 JDK 不能触发的原因—— _tfactory
在大版本下,JDK1.7 和 1.8 中,com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl
类是有所不同的。
当然,在小版本较高的 1.7 和某些 1.8 的还是能够成功触发的,具体的可自行测试。
区别在于新建 TransletClassLoader 类实例的代码,其中调用了 _factory
属性,但是该属性值我们没有在 PoC 中设置,默认为 null,于是就会抛出异常了。
而 Jackson 也是无法设置 _tfactory
的,因为 _tfactory
在原本的 TemplatesImpl
类中都没有 getter 或 setter 方法,这就拿不到了。
0x06 补丁分析
这里将 jackson-databind-2.7.9 换成 jackson-databind-2.7.9.1。
尝试运行会报错如下,显示因为某些安全原因禁止了该类的加载:
调试分析,在调用 BeanDeserializerFactory.createBeanDeserializer()
函数创建 Bean 反序列化器的时候,其中会调用 checkIllegalTypes()
函数提取当前类名,然后使用黑名单进行过滤:
Ref
- 本文标题:Jackson 反序列化(二)CVE-2017-7525
- 创建时间:2023-12-07 20:06:00
- 本文链接:2023/12/07/Jackson-反序列化(二)CVE-2017-7525/
- 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!