CVE-2017-7525 jackson rce主线流程分析

环境:

  • jdk1.7
  • jackson-databind 2.8.8

成功弹出计算器

this._getter为:public synchronized java.util.Properties com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getOutputProperties()
instance的_name=a.b,_bytecodes是传入的字符串

  • deserializeAndSet:116, SetterlessProperty (com.fasterxml.jackson.databind.deser.impl)

toModify = this._getter.invoke(instance);

此时传入的JSON会在vanillaDeserialize方法中遍历,遍历到outputProperties进入

  • deserializeAndSet:106, MethodProperty (com.fasterxml.jackson.databind.deser.impl)

调用方法:this._setter.invoke(instance, value);
此时this.setter为private synchronized void com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.setTransletBytecodes(byte[][])

  • vanillaDeserialize:276, BeanDeserializer (com.fasterxml.jackson.databind.deser)

和之前同样的操作,进入prop.deserializeAndSet(p, ctxt, bean);

  • deserialize:140, BeanDeserializer (com.fasterxml.jackson.databind.deser)

return this.vanillaDeserialize(p, ctxt, p.nextToken()); 判断是否是jsonstart的token后进入vanillaDeserialize,进入第二层的JSON解析

  • _deserialize:116, AsArrayTypeDeserializer (com.fasterxml.jackson.databind.jsontype.impl)

进行了一些不是很懂的操作之后,调用Object value = deser.deserialize((JsonParser)p, ctxt);方法,该方法是基于bean的对象(POJO)的主要反序列化方法。

  • deserializeTypedFromAny:71, AsArrayTypeDeserializer (com.fasterxml.jackson.databind.jsontype.impl)

return this._deserialize(jp, ctxt); 传递给_deserialize方法,_deserialize解释:处理类型信息包装器的方法,找到要使用的实际子类型反序列化器,并调用它来进行实际的反序列化。

  • deserializeWithType:553, UntypedObjectDeserializer$Vanilla (com.fasterxml.jackson.databind.deser.std)

return typeDeserializer.deserializeTypedFromAny(p, ctxt);传递给deserializeTypedFromAny方法

  • deserialize:502, SettableBeanProperty (com.fasterxml.jackson.databind.deser)
1
2
3
4
5
6
7
8
public final Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
JsonToken t = p.getCurrentToken();
if (t == JsonToken.VALUE_NULL) {
return this._valueDeserializer.getNullValue(ctxt);
} else {
return this._valueTypeDeserializer != null ? this._valueDeserializer.deserializeWithType(p, ctxt, this._valueTypeDeserializer) : this._valueDeserializer.deserialize(p, ctxt);
}
}

判断token,然后传递给deserializeWithType方法

  • deserializeAndSet:111, FieldProperty (com.fasterxml.jackson.databind.deser.impl)

Object value = this.deserialize(p, ctxt);

  • vanillaDeserialize:276, BeanDeserializer (com.fasterxml.jackson.databind.deser)

Object bean = this._valueInstantiator.createUsingDefault(ctxt); p.setCurrentValue(bean);设置当前的bean
此时:p-JsonParser,用于读取api的基类。ctxt-DeserializationContext,扩展版p

1
2
3
4
5
6
7
8
9
10
11
12
13
do {
p.nextToken();
SettableBeanProperty prop = this._beanProperties.find(propName);
if (prop != null) {
try {
prop.deserializeAndSet(p, ctxt, bean);
} catch (Exception var8) {
this.wrapAndThrow(var8, bean, propName, ctxt);
}
} else {
this.handleUnknownVanilla(p, ctxt, bean, propName);
}
} while((propName = p.nextFieldName()) != null);

遍历JSON的核心部分。
SettableBeanProperty prop = this._beanProperties.find(propName); 将属性名映射到属性中
if (prop != null) { prop是包含反序列化属性的基类
prop.deserializeAndSet(p, ctxt, bean); 使用合适的方法设置,调用合适的方法,给解析器。

  • deserialize:140, BeanDeserializer (com.fasterxml.jackson.databind.deser)

if (p.isExpectedStartObjectToken()) {

if (this._vanillaProcessing) {判断是否开始标记/是否是未启用特殊功能的JSON

进入return this.vanillaDeserialize(p, ctxt, p.nextToken()

  • _readMapAndClose:3798, ObjectMapper (com.fasterxml.jackson.databind)

if (t == JsonToken.VALUE_NULL) { 首先判断是否进入JSON结尾,首次进入函数t为START_OBJECT
进入} else if (t != JsonToken.END_ARRAY && t != JsonToken.END_OBJECT) {分支
DeserializationConfig cfg = this.getDeserializationConfig();得到反序列化的配置设置
DeserializationContext ctxt = this.createDeserializationContext(p, cfg);的作用:创建DeserializationContext实例来反序列化单个root value
p创建为ctxt的过程中为ObjectMapper添加扩展API进行调用,以及实现基类留下的某些抽象部分。

1
2
3
`} else {
result = deser.deserialize(p, ctxt);

开始反序列化

  • readValue:2842, ObjectMapper (com.fasterxml.jackson.databind)

json字符串经过_jsonFactory.createParser处理,目标类经过_typeFactory.constructType处理,进入_readMapAndClose函数
这个方法将传入的String和目标类转换为基本的解析器基类用于后面的数据处理。

  • main:54, Exploit

传入json字符串和反序列化目标类


到最后一步弹出计算机的.invoke()不太明白,留个坑在这里

下期:CVE-2017-17485主线分析

支持一下
扫一扫,支持forsigner