S2-052漏洞分析及官方缓解措施无效验证

作者:廖新喜

综述

2017年9月5日,Apache Struts 发布最新的安全公告,Apache Struts 2.5.x 和 2.3.x 的 REST 插件存在远程代码执行的高危漏洞,漏洞编号为 CVE-2017-9805(S2-052)。漏洞的成因是由于使用 XStreamHandler 反序列化 XStream 实例的时候没有任何类型过滤导致远程代码执行。

相关链接如下:
https://cwiki.apache.org/confluence/display/WW/S2-052

影响版本:
Struts 2.1.2 – Struts 2.3.33, Struts 2.5 – Struts 2.5.12

规避方案:
立即升级到Struts 2.5.13 or Struts 2.3.34

技术分析

根据官方的描述信息来看,是 REST 插件使用到 XStreamHandler 处理 xml 数据的时候,由于未对 xml 数据做任何过滤,在进行反序列将 xml 数据转换成 Object 时导致的 RCE。

0x01 环境搭建

官方地址下载所有源码包,找到其中的 struts2-rest-showcase.war 直接部署到 tomcat 就行,当然我更喜欢手动编译,直接通过 Maven 编译即可。具体的部署过程这里就不详细描述,不过有点是需要注意的,由于 javax.imageio 的依赖关系,我们的环境的 jdk 版本需要是 jdk8 以上,jdk8 某些低版本也是不行的,本文作者的版本是 jdk8_102,后续的一些验证都是在这个版本上做的。

0x02 补丁分析

环境搭建好了之后,首先我们来看下 rest 插件的相关配置

从这个文件中就可以看出 XStreamHanler 就是Content-Type:xml的默认处理句柄,而且可以看出xml是默认支持格式,这也就是说存在rest插件就会存在XStream的反序列化漏洞。

接着看看官方的修复方案,补丁地址:https://github.com/apache/struts/commit/19494718865f2fb7da5ea363de3822f87fbda264

在官方的修复方案中,主要就是将 xml 中的数据白名单化,把 Collection 和 Map,一些基础类,时间类放在白名单中,这样就能阻止 XStream 反序列化的过程中带入一些有害类。

0x03 POC的生成

目前公开的 Poc 是基于 javax.imageio 的,这是能直接本地执行命令,但是 marshelsec 提供了11个 XStream 反序列化库,其中大部分都是基于 JNDI,具体包含:CommonsConfiguration, Rome, CommonsBeanutils, ServiceLoader, ImageIO,
BindingEnumeration, LazySearchEnumeration, SpringAbstractBeanFactoryPointcutAdvisor, SpringPartiallyComparableAdvisorHolder, Resin, XBean,
从外部请求类完成反序列化。

0x04 漏洞验证及简单分析

下图是一个简单的验证分析图,从Poc中可以看出,请求是PUT,请求的url后缀带xml,请求的Content-Type为delicious/bookmark+xml,请求的xml的前缀是 <set>.

接着我们看下触发的执行调用栈:

在 XStreamHanler.toObject 调用了 XStream 的 fromXml,从而进入反序列化流程。

0x05 官方临时缓解措施不起作用

官方给出的缓解措施 <constant name="struts.action.extension" value="xhtml,,,json" />,从字面意思也能看出来,这个是针对 action 的后缀的,也就是说如果后缀不带 xml 也就可以绕过。下面给出测试用例,从我们的 poc 中也可以看出,POST 请求不带 xml 的后缀直接忽视这个缓解措施。所以说 Struts 的官方也不怎么复制,没测试过的东西就直接放出来。XStream 只跟 Content-Type 有关,如果 Content-Type 中含有 xml,则会交给 XStream 处理,所以 poc 该怎么使还怎么使,并且目前最大的问题就是国内的解决都是使用的这个无效的官方解决方案,下面看下我们的验证:

从图上可以看出,我们已经去除了 xml 的支持,下面来看看 Payload 的执行效果:

成功弹出计算器,这也就验证了我们的想法。同时通过两个不同poc的比较,我们也能发现一些端倪,Content-Type支持xml的几种格式,POST 请求,PUT 请求,GET 请求甚至是自定义请求都是能触发漏洞,我们可以将poc中 <map><entry>换成 <set> 也能触发漏洞。同时由于 XStream 本身的 Poc 多达十一种,做好安全防御确实比较艰难。