当地时间10月3日,来自LGTM的安全研究人员发布博客公布了多个 Apache Struts双重评估远程代码执行漏洞。该研究人员利用以下步骤定位到漏洞,首先通过QL查询能导致双重评估的代码模式来发现可能存在的漏洞,其次利用污点跟踪寻找OGNL的入口点方法,最后经过进一步分析来确定漏洞,详细过程见参考链接。
发现的漏洞已于2018年4月上报官方,但是Struts安全团队于8月28日回复拒绝了漏洞问题,认为此类漏洞并非源于框架本身,因为它是由于依赖于框架的用户将一些不受信任的数据放入模板或配置文件中而产生,所以用户有责任确保自己的配置不会满足触发双重评估漏洞的条件,并且不打算进行修补。但是该研究人员表示,由于双重评估漏洞的行为相当直观,如果开发人员配置不当,便很容易将应用置于危险之中,故公开披露这些问题,以便让更多用户了解。
漏洞描述
Struts tags中的结果
以下是Struts tags中发现的结果,触发它们的配置不太可能在现实的应用程序中找到,详情查看参考链接 Double evaluation results in Struts tags 标题。
UIBean及其子类
抽象类UIBean中有两个属性可以进行双重评估。一个是name属性,首先通过此处的findString方法进行评估,然后再次在这里进行评估。另一个是key属性,该属性用于在配置中未设置 name 属性时配置该属性。
Param标签与Bean标签共用
根据value属性是否设置,name首先在此处或在这两处评估属性。然后,进入addParameter的方法component,比如这里。
Text标签
name 属性首先通过 findString评估,然后作为 defaultMesssage 参数传递给TextProviderHelper的getText方法。在getText方法中,如果searchStack设置为true,则将再次对defaultMessage进行评估。
参考链接:
https://lgtm.com/blog/apache_struts_double_evaluations
Struts 配置中的结果
以下易受攻击配置不符合 struts 建议,其中AliasInterceptor甚至不需要使用 ${..} 或者 %{..}语法。
AliasInterceptor
以下代码中有两个地方进行双重评估:
final Map<String, String> parameters = config.getParams(); //<-- parameters comes from config file. if (parameters.containsKey(aliasesKey)) { String aliasExpression = parameters.get(aliasesKey); //<-- `aliasExpression` tainted. ValueStack stack = ac.getValueStack(); Object obj = stack.findValue(aliasExpression); //<-- first evaluation. if (obj != null && obj instanceof Map) { ... Map aliases = (Map) obj; for (Object o : aliases.entrySet()) { Map.Entry entry = (Map.Entry) o; String name = entry.getKey().toString(); //<-- `name` is tainted String alias = (String) entry.getValue(); //<-- `alias` is tainted Evaluated value = new Evaluated(stack.findValue(name)); //<-- second evaluation of `name` ... if (value.isDefined()) { try { newStack.setValue(alias, value.get()); //<-- second evaluation of `alias`
这将影响类似以下这样的配置:
<param name="aliases">#{ #parameters['name'][0] : value }</param> <interceptor-ref name="alias"/> <interceptor-ref name="basicStack"/> <result name="success">good_result.ftl</result>
或者
<param name="aliases">#{ 'name' : #parameters['value'][0] }</param> <interceptor-ref name="alias"/> <interceptor-ref name="basicStack"/> <result name="success">good_result.ftl</result>
当收到如下请求时,可能会出现意外:
https://myDomain.com/myApp?name=expr
请注意,在以上两种情况下,request参数的值都被直接解释为OGNL,而不需要包含在特殊 %{..}或${..}语法中。
ServletActionRedirectResult, ActionChainResult, PostbackResult
介于 ServletActionRedirectResult 中的处理流程,当接收到 https://myDomain.com/myApp?redirect=%{expr} 请求时,以下几种配置可能引发远程代码执行。
<result type="redirectAction"> <param name="actionName">${#parameters['redirect']}</param> <param name="namespace">/namespace</param> </result>
或者
<result type="redirectAction"> <param name="actionName">myAction</param> <param name="namespace">${#parameters['redirectNamespace']}</param> </result>
或者
<result type="redirectAction"> <param name="actionName">myAction</param> <param name="namespace">/namespace</param> <param name="method">${#parameters['redirectMethod']}</param> </result>
StreamResult
接收请求 https://myDomain.com/myApp?inputName=expr时受影响配置如下:
<result name="success" type="stream"> <param name="contentType">image/jpeg</param> <param name="inputName">${#parameters['inputName'][0]}</param> <param name="contentDisposition">attachment;filename="document.pdf"</param> <param name="bufferSize">1024</param> </result>
参考链接:
https://lgtm.com/blog/apache_struts_double_evaluations
安全建议
1、不要在 Struts tags 或者 Struts 配置中使用 ${..}或%{..}语法(包括XML配置和带有convention plugin的代码内配置)。如果必须使用这些语法之一,那么请不要将用户输入传递给它们。
2、不要将 AliasInterceptor与用户输入设置的任何名称或别名一起使用。
3、不要试图通过在用户输入中查找${..}或%{..}来清理OGNL 输入。一些标签或配置以及AliasInterceptor仅是将用户输入作为OGNL,而不将它们包装在特殊${..}或%{..}语法中,这使得很难对输入进行检查。
更多详细内容见参考链接 Mitigation 标题。
参考链接:
声 明
=============
本安全公告仅用来描述可能存在的安全问题,绿盟科技不为此安全公告提供任何保证或承诺。由于传播、利用此安全公告所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,绿盟科技以及安全公告作者不为此承担任何责任。绿盟科技拥有对此安全公告的修改和解释权。如欲转载或传播此安全公告,必须保证此安全公告的完整性,包括版权声明等全部内容。未经绿盟科技允许,不得任意修改或者增减此安全公告内容,不得以任何方式将其用于商业目的。
关于绿盟科技
==============
北京神州绿盟信息安全科技股份有限公司(简称绿盟科技)成立于2000年4月,总部位于北京。在国内外设有30多个分支机构,为政府、运营商、金融、能源、互联网以及教育、医疗等行业用户,提供具有核心竞争力的安全产品及解决方案,帮助客户实现业务的安全顺畅运行。
基于多年的安全攻防研究,绿盟科技在网络及终端安全、互联网基础安全、合规及安全管理等领域,为客户提供入侵检测/防护、抗拒绝服务攻击、远程安全评估以及Web安全防护等产品以及专业安全服务。
北京神州绿盟信息安全科技股份有限公司于2014年1月29日起在深圳证券交易所创业板上市交易,股票简称:绿盟科技,股票代码:300369。