前言
最近有个需求,用Xstream反序列化打个内存马,从通用性来讲,肯定用1.4.17的洞去打应用范围最广。众所周知,Xstream官方会提供其漏洞的poc。在我实验之下,1.4.17的几个poc只要涉及到任意java代码执行的都会报错,纯调用java.lang.Runtime.exec()的却不会报错。在我调试之下发现了其奥秘,本文就是解决Xstream任意java代码执行报错的问题。
正文
CVE-2021-39149
官方poc如下
1 | <linked-hash-set> |
坑点1
首先报了一个不识别字段的错误
接下来我们排错,在this.handleUnknownField这里下端点,然后debug运行
从下图可以看到,这个方法的入参fieldDeclaringClass=sun.tracing.dtrace.DTraceProbe,fieldName=com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl。这表示xstream希望从xml中还原sun.tracing.dtrace.DTraceProbe类中字段名为com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl的字段值。然而sun.tracing.dtrace.DTraceProbe中肯定是没有这个字段名的字段的。但为什么会发生这种事呢?我记得xml字串里面com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl是作为类进行反序列化赋值的呀。那么原因一定还是在xml字串中。
最终排查xml字串,我发现了一个诡异的bug。上面箭头那里的proxy居然自己闭合了。。。这就直接导致了com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl变成了sun.tracing.dtrace.DTraceProbe的一个字段进行解析了。
正确写法应当如下,删除</proxy>中的/符号,使<proxy>和后面的</proxy>闭合,这样com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl就可以作为一个类进行反序列化赋值了。
1 | <proxy class='com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl' serialization='custom'> |
不过你以为这就结束了?
坑点2
在我信心慢慢的运行poc的时候,却发现又报错了,这次错误发生在TemplatesImpl反序列化的时候,老样子我们打个断点去看看。
错误是从下图箭头位置抛出的,因此我们跟如进入,看这个readBoolean是做什么的
跟了一步就发现,这个方法是用来读取一个Bool类型的标签的
然而我们的com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl中除了<defalut>标签,就干干净净的了,从哪里能读到Bool值呢,所以就会直接抛出异常了。这里我们需要手动加一个bool标签,供TemplatesImpl反序列化得时候读取即可。
从官方文档可以看到bool标签是如下写法
1 | <boolean>true</boolean> |
在我们得实际情况中,我是希望bool值为false得,这样我就不需要调用第二个readObject造成后续得麻烦。
最后修改得TemplatesImpl如下,在</default>后面加了一个false的Bool标签。
1 | <com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl> |
poc成品
最后得到可用的poc,作用为弹calc,要改的话直接修改byte-array里面的内容就行了
1 | <linked-hash-set> |
结尾
你们相信这是官方的一个失误吗(狗头)