Struts2 s2-052 REST插件远程代码执行 技术分析与防护方案
2017-09-07
综述
2017年9月5日,Apache Struts发布最新的安全公告,Apache Struts 2.5.x以及之前的部分2.x版本的REST插件存在远程代码执行的高危漏洞,漏洞编号为CVE-2017-9805(S2-052)。漏洞的成因是由于使用XStreamHandler反序列化XStream实例的时候没有任何类型过滤导致远程代码执行。
相关地址:
https://struts.apache.org/docs/s2-052.html
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.3.34
· Struts 2.5.13
漏洞分析
根据官方的描述信息来看,是REST插件使用到XStreamHandler处理xml数据的时候,由于未对xml数据做任何过滤,在进行反序列将xml数据转换成Object时导致的RCE。
环境搭建
从官方地址(https://archive.apache.org/dist/struts/2.5/struts-2.5-all.zip)下载所有源码包,找到其中的struts2-rest-showcase.war直接部署到tomcat就行,当然我更喜欢手动编译,直接通过Maven编译即可。具体的部署过程这里就不详细描述,不过有点是需要注意的,由于javax.imageio的依赖关系,我们的环境的jdk版本需要是jdk8以上,jdk8某些低版本也是不行的,本文作者的版本是jdk8_102,后续的一些验证都是在这个版本上做的
补丁分析
环境搭建好了之后,首先我们来看下rest插件的相关配置
从这个文件中就可以看出XStreamHanler就是Content-Type:xml的默认处理句柄,而且可以看出xml是默认支持格式,这也就是说存在rest插件就会存在XStream的反序列化漏洞。
接着看看官方的修复方案,补丁地址:https://github.com/apache/struts/commit/19494718865f2fb7da5ea363de3822f87fbda264
在官方的修复方案中主要就是将xml中的数据白名单化,把Collection和Map,一些基础类,时间类放在白名单中,这样就能阻止XStream反序列化的过程中带入一些有害类。
POC的生成
目前公开的Poc是基于javax.imageio的,这是能直接本地执行命令,但是marshelsec提供了11个XStream反序列化库,其中大部分都是基于JNDI,具体包含:CommonsConfiguration Rome CommonsBeanutils ServiceLoader ImageIO
BindingEnumeration LazySearchEnumeration SpringAbstractBeanFactoryPointcutAdvisor SpringPartiallyComparableAdvisorHolder Resin XBean,
从外部请求类完成反序列化。
漏洞验证及简单分析
下图是一个简单的验证分析图,从Poc中可以看出,请求是PUT,请求的url后缀带xml,请求的Content-Type为delicious/bookmark+xml,请求的xml的前缀是
接着我们看下触发的执行调用栈:
在XStreamHanler.toObject调用了XStream的fromXml,从而进入反序列化流程。
官方临时缓解措施不起作用
官方给出的缓解措施
将下图红框部分修改为:
具体修改方法为:
使用压缩工具打开对应的jar包,这里以struts2-rest-plugin-2.5.10.1.jar为例:
将struts-plugin.xml进行提取,修改对应的配置,重新放入压缩包中,替换原有配置:
重启服务器即可。
停止xml解析后,再次访问xml请求时,应用就会显示404错误,不再支持xml格式数据的解析。
下面给出测试用例,从我们的poc中也可以看出,POST请求不带xml的后缀直接忽视这个缓解措施。XStream只跟Content-Type有关,如果Content-Type中含有xml,则会交给XStream处理,所以poc该怎么使还怎么使,下面看下我们的验证:
从图上可以看出,我们已经去除了xml的支持,下面来看看Payload的执行效果:
成功弹出计算器,这也就验证了我们的想法。同时通过两个不同poc的比较,我们也能发现一些端倪,Content-Type支持xml的几种格式,POST请求,PUT请求,GET请求甚至是自定义请求都是能触发漏洞,我们可以将poc中
技术防护方案
官方修复方案
Struts官方已经发布了最新版本,请受影响的受用尽快升级来进行防护。
参考链接:
· Struts 2.3.34:
https://cwiki.apache.org/confluence/display/WW/Version+Notes+2.3.34
· Struts 2.5.13:
https://cwiki.apache.org/confluence/display/WW/Version+Notes+2.5.13
香港正版挂牌防护建议
香港正版挂牌检测类产品与服务
1、 公网资产可使用绿盟云 紧急漏洞在线检测,检测地址如下:
https://cloud.nsfocus.com/#/krosa/views/initcdr/productandservice?page_id=12
2、内网资产可以使用香港正版挂牌的远程安全评估系统(RSAS V6)或 Web应用漏洞扫描系统(WVSS),以及入侵检测系统(IDS) 进行检测。
远程安全评估系统(RSAS V6)
http://update.nsfocus.com/update/listRsasDetail/v/vulweb
Web应用漏洞扫描系统(WVSS)
http://update.nsfocus.com/update/listWvss
入侵检测系统(IDS)
http://update.nsfocus.com/update/listIds
通过上述链接,升级至最新版本即可进行检测
使用香港正版挂牌防护类产品(IPS/IDS/NF/WAF)进行防护:
入侵防护系统(IPS)
http://update.nsfocus.com/update/listIps
下一代防火墙系统(NF)
http://update.nsfocus.com/update/listNf
Web应用防护系统(WAF)
http://update.nsfocus.com/update/wafIndex
通过上述链接,升级至最新版本即可进行防护!
临时解决方案
添加xml过滤器,将所有的contentType为“application/xml”的请求全部过滤。该方案会导致所有contentType为application/xml的请求失效,为暂时性的防护方案。
具体过滤器代码如下:
public void doFilter(ServletRequest request ServletResponse response FilterChain chain) throws IOException ServletException { if (request.getContentType() != null) { String contentType = request.getContentType().toLowerCase(Locale.ENGLISH); if (contentType != null && contentType.contains("application/xml")) { response.getWriter().write("Reject!"); } else { chain.doFilter(request response); } } else { chain.doFilter(request response); } } |
添加该过滤器后,使用POC测试,可以拦截:
需要注意的是,新版本使用的默认限制策略会导致REST的一些函数停止工作,会对一些业务造成影响,建议使用以下新的接口:
org.apache.struts2.rest.handler.AllowedClasses
org.apache.struts2.rest.handler.AllowedClassNames
org.apache.struts2.rest.handler.XStreamPermissionProvider
声 明
本安全公告仅用来描述可能存在的安全问题,香港正版挂牌不为此安全公告提供任何保证或承诺。由于传播、利用此安全公告所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,香港正版挂牌以及安全公告作者不为此承担任何责任。香港正版挂牌拥有对此安全公告的修改和解释权。如欲转载或传播此安全公告,必须保证此安全公告的完整性,包括版权声明等全部内容。未经香港正版挂牌允许,不得任意修改或者增减此安全公告内容,不得以任何方式将其用于商业目的。