深入理解POJONode的toString调用任意类getter方法原理
一、前言
1.1 说说废话
由于最近刚入门java安全,学了CC链、CB链,想要去找一些CTF反序列化题目练练手,然后突然发现,原来CC链、CB链不是尽头,只是开始,还有一大堆的链子等着我去结合CC、CB链进行利用;
通过wp学习反序列化利用的过程中,发现POJONode#toString真的是高频出现啊,真不理解这是啥玩意儿,咋这么好用呢?通过一顿资料搜索发现,原来是Jackson的原生反序列化链子之一,之前学Jackson的时候没看到这个,现在补上;
这里就不在赘述Jackson反序列化的基础知识了,直接分析相关类的内容;
1.2 环境
- jdk8u65
- jackson-databind 2.7.9
- jackson-core 2.7.9
- jackson-annotations 2.7.9
1 |
|
1.3 利用限制
存在jackson环境,目前了解对版本无要求、对jdk版本也无要求
二、POJONode#toString
2.1 方法执行流程分析
首先,说一下POJONode本身是没有重写toString()
方法的,所以它调用的toString()
方法是它的父类的toString()
方法;
跟进父类ValueNode
,发现也没有重写toString()
,因此我们继续跟进ValueNode
的父类BaseJsonNode
类,可以看到toString()
方法的具体实现。
继续跟进nodeToString()
方法,查看具体实现;可以发现其调用了writeValueAsString()
方法进行序列化
总结一下,POJONode#toString
方法执行了对自身对象的序列化;
2.2 Jackson序列化流程
BaseJsonNode#toString -> InternalNodeMapper#nodeToString -> ObjectWriter#writeValueAsString -> ObjectWriter#_writeValueAndClose -> ObjectWriter#serialize -> DefaultSerializerProvider#serializeValue -> DefaultSerializerProvider#serialize -> DefaultSerializerProvider#_serialize -> SerializableSerializer#serialize -> POJONode#serialize -> SerializerProvider#defaultSerializeValue -> JsonSerializer#serialize -> BeanSerializer#serialize - > BeanSerializerBase#serializeFields -> BeanPropertyWriter#serializeAsFields
在跟这条序列化链子的过程中,发现确实是复杂到了极点,还是不跟了吧。
上述知识找到了调用getter的链子,它会调用传入POJONode的对象的所有属性的getter函数,从而实现任意getter调用;
具体的对象属性如何获取和getter方法的获取还要继续分析findTypedValueSerializer
函数,这边就不分析了,知道结论和用法就结束吧!
三、POJONode反序列化Gadget
1 |
|