前言
研究一些jar包的漏洞,比较常用的有Xstream等,先从Xstream历史漏洞看起,拿CVE-2020-26258这个SSRF分析一下。
POC
1 | import com.thoughtworks.xstream.XStream; |
环境准备
pom中导入1.4.14版本的xstream
1 | <dependencies> |
代码分析
先在AbstractReferenceUnmarshaller的第58行打上断点,从这里开始xstream准备解析payload中map标签内的内容。
在MapConveter.putCurrentEntryIntoMap的78行打上断点,这里开始解析Entry。
每一次的reader.moveDown()都会把向栈中压入一个标签,从下图可以看到,当前的栈中已经有map和empty了。从payload看,下一次压入的应该是jdk.nashorn.internal.objects.NativeString这个标签。
因此在压栈之后执行的this.readItem(reader, context, current)的目的是将下面的xml转化为Object,及一个反序列化生成类的过程。
1 | <jdk.nashorn.internal.objects.NativeString> |
这里的this.readItem在文章中不贴了,因为具体细节很长,大家可以自己跟,在我看来分析的文章里说一下整体的思路起引导左右即可,说的太细会代替读者的自我思考,对吸收反而不易。
this.readItem后面调用的是reader.moveUp,作用是出栈。然后将反序列化的object返回。
这里说明一下这个返回的Object的类型为jdk.nashorn.internal.objects.NativeString。
然后又回到了MapConverter.putCurrentEntryIntoMap的第79行,开始解析Entry中value的值,value的值其实就是test,由payload中下面的xml解析得来
1 | <string>test</string> |
接下来就要到漏洞触发点的入口了,target.put(key,value)。由于target为HashMap类型这里在HashMap.put处打断点,然后F7跟入。
hash(Key)这里跟入
key.hashCode()跟入
要记得,这里的key为jdk.nashorn.internal.objects.NativeString类型。
this.getStringValue()跟入
然后会调用到 this.value.toString()
jdk.nashorn.internal.objects.NativeString这个实例化类的value为com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data类型,因此是调用Base64Data的toString方法。我们继续跟入。
跟入this.get()
接着会调用到一行代码
1 | InputStream is = this.dataHandler.getDataSource().getInputStream(); |
这里得到的最后为我们payload中的javax.activation.URLDataSource,因此触发ssrf。
结论
HashMap在put key的时候,会调用到key.hashCode方法,这个之前在某条gadgat调用链也用到过,要加深记忆。