您的位置:首页 > 运维架构 > Apache

Apache Struts 2漏洞分析(CVE-2018-11776/S2-057)

2018-10-22 11:32 1026 查看

概述
定义XML配置时如果namespace值未设置且上层动作配置(Action Configuration)中未设置或用通配符namespace时可能会导致远程代码执行。

url标签未设置value和action值且上层动作未设置或用通配符namespace时可能会导致远程代码执行。

官方解决方案
升级至版本2.3.35或2.5.17。这两个版本仅仅只是更新了安全补丁,不存在兼容性问题。

临时解决方案
推荐用户及时更新,但如果不想更新,可暂时使用官方提供的临时解决方案:当上层动作配置中未设置或使用通配符namespace时,验证所有XML配置中的namespace,同时在JSP中验证所有url标签的value和action。

影响范围

所有Struts2开发者及用户

漏洞影响

有可能会导致远程代码执行

最高安全风险

关键

推荐防护措施

更新至2.3.35或2.5.17

影响版本

Struts 2.3 – Struts 2.3.34, Struts 2.5 – Struts 2.5.16

其余版本也可能会受到影响

漏洞报告人

Man Yue Mo@Semmle Security Research team

CVE编号

CVE-2018-11776

示例如下:

<struts>
<package ....>
<action name="a1">
<result type="redirectAction">
<param name="actionName">a2.action</param>
</result>
</action>
</package>
</struts>

模板中的url tag
当模板关联的tag没有提供namespace以及包含无value和action的<s:url …>tag时有安全风险。

示例如下:

<action name="help" namespace="/*">
<result>/WEB-INF/help.jsp</result>
</action>
<s:url includeParams="get">
<s:param name="id" value="%{'22'}" />
</s:url>

漏洞细节Semmle Security将在近期公布
以ServletActionRedirectResult.java为例:

首先,getNamespace()调用通过变量namespace传入ActionMapping构造函数中。

public void execute(ActionInvocation invocation) throws Exception {
actionName = conditionalParse(actionName, invocation);
if (namespace == null) {
namespace = invocation.getProxy().getNamespace();  //<--- source
} else {
namespace = conditionalParse(namespace, invocation);
}
if (method == null) {
method = "";
} else {
method = conditionalParse(method, invocation);
}

String tmpLocation = actionMapper.getUriFromActionMapping(new ActionMapping(actionName, namespace, method, null)); //<--- namespace goes into constructor of ActionMapping

setLocation(tmpLocation);

可以看到,getUriFromActionMapping()通过ActionMapping对象返回URL字符串,接着通过tmpLocation传入setLocation()。

接着setLocation()将location传入StrutsResultSupport类。

public void setLocation(String location) {
this.location = location;

}
接着在ServletActionResult上执行execute()。

String tmpLocation = actionMapper.getUriFromActionMapping(new ActionMapping(actionName, namespace, method, null));

setLocation(tmpLocation);

super.execute(invocation);

location被传入conditionalParse()。

public void execute(ActionInvocation invocation) throws Exception {
lastFinalLocation = conditionalParse(location, invocation);
doExecute(lastFinalLocation, invocation);

}
conditionalParse()将location传入translateVariables(),在此参数处理为OGNL表达式。

protected String conditionalParse(String param, ActionInvocation invocation) {
if (parse && param != null && invocation != null) {
return TextParseUtil.translateVariables(
param,
invocation.getStack(),
new EncodingParsedValueEvaluator());
} else {
return param;
}
}

综上,当ServletActionRedirectResult中未设置namespace时,将会从ActionProxy中取namespace作为OGNL。因此此处可修改struts-actionchaining.xml测试:

<struts>
<package name="actionchaining" extends="struts-default">
<action name="actionChain1" class="org.apache.struts2.showcase.actionchaining.ActionChain1">
<result type="redirectAction">
<param name = "actionName">register2</param>
</result>
</action>
</package>
</struts>

启动应用,访问特定URL触发漏洞,绕过OGNL沙箱后可造成命令执行。

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: