With this post we continue our series about enterprise software and SAP security articles. I will cover the basics of the HANA Database network protocol and review how authentication is handled in the protocol.
HANA Database is an in-memory database developed and sold by SAP. It has become the enterprise software company’s flagship product, by sitting at the core of SAP’s data management and advanced analytics offering. HANA serves also as the foundation of the technological platform on which its ERP, CRM and SRM run, by having it not only act as the database layer but additionally as an application server. Web-based business applications can be developed and run on top of the HANA platform. In this blogpost I’ll share a little bit about the basics of the network protocol that the HANA database (some time ago also called HDB from “Hybrid Data Base”) uses to communicate with clients, and discuss some particular scenarios concerning password-based authentication. Throughout the rest of the article we will refer to HANA and HDB as on-premise HANA Platform instances. Most of the content applies to HANA Cloud Platform and the SAP HANA Service in AWS, GCP and other cloud providers as well, but there might be small differences.
Studying the inner workings of networking protocols can be, not only funny to some of us, but also valuable for different purposes. Luckily, specifications of the protocol used by the HANA database, called “HANA SQL Command Network protocol”, have been published by SAP since its version 1.0 SPS 12, released in 2018. This makes the research of the protocol easier than other binary-based protocols that are not only proprietary but whose specifications are not publicly available. In the same line, besides the officially supported clients and for which the code is not publicly available, SAP has published multiple implementations of the protocol in different programming languages as Open Source. This includes for example Node.js (node-hdb), Python (PyHDB) and Golang (go-hdb). Other implementations are also available from other sources, such as the one for Rust (rust-hdbconnect).
What is the deal then if the protocol is so open and widely known? Well, it turns out that studying and independently implementing the protocol can be important for different reasons, mainly:
- First, the implementation of the protocol in the server and the official clients differ slightly from the specifications. While SAP has made very good work at documenting the finer points and details about the packet formats and structures involved, new versions added variants and new types that are not all fully covered in the documentation. Particularly from a security standpoint, the devil is in the details so understanding these ins and outs can be valuable.
- Second, from an offensive standpoint understanding all things related to the authentication process is key. Authentication is one of the pieces less covered in the different open source libraries, as only the basic mechanisms are implemented.
- Third, while having the source code allows for manually tweaking some of the structures, the libraries are not intended for that purpose. Those libraries are designed and coded for building valid packets and sending them in the right way that the other party expects. Implementing attacks and workflows that differ from the expected logic might be challenging, such as mutating and crafting invalid packets for fuzzing or other purposes.
- Finally, there are no tools available to easily troubleshoot and analyze the network traffic while playing with the different components.
HANA SQL Command Network Protocol
Let’s take a high-level look then at the protocol itself. The protocol used by SAP HANA database clients to communicate with the servers is called “HANA SQL Command Network Protocol”. As already mentioned, its specifications have been made available by SAP since version 1.0 SPS 12. The latest specification available is for the version 2.0 SPS 03, published in October 2019.
The protocol uses binary messages, and defines the main mechanism used for: – Connecting and authenticating a client to the server. – Executing prepared statements. – Handling result sets and large object data. – Using distributed transaction handling.
We will not go into the details about the structures that form the protocol packets, as those are very well described in the documentation. One important characteristic is that the communication between client and server is synchronous: client can only perform a new request once the reply to the previous one was fully received. Another important point is that, as the protocol is designed to handle large amount of data, it is very flexible by nature. Very weird combinations of structures can be found, with packets spanning multiple TCP packets, offsets, and packet numbers, and containing variable number of “Segments” and “Parts” kinds. Compression is also supported, but optionally configured on both clients and servers.
Dissecting HANA HDB Protocol Traffic
Before jumping to develop any type of packet crafting code, a key in the process is being able to understand the traffic generated with the use of official and supported tools. This allows translating the bytes in the wire to actual structures that (should) match with the formats defined in the specifications. Our tool of choice for this task is Wireshark, and we are very familiar with it from our continued work researching other SAP protocols and making them available as an Open Source plugin.
We found a very interesting project with a Lua-based dissector of the HANA SQL Command Network protocol by Koji Shinkubo. While it served as an inspiration, it was not possible to reuse that code in our plugin, which is based on C/C++ dissectors. In addition, the protocol was not implemented in full and lacked several parts.
We decided to add a new dissector to our plugin to support the new protocol. As always with these types of tools, recreating the entire protocol is a big-time endeavor, so it cannot be counted as a finished task but instead as a work in progress effort. We focused on the initial parts of the communications and tried to cover most of the initialization and authentication phases. It resulted in decent support of the protocol and the results were very helpful at the time for understanding what is going on between the client and the server.
The initial version of the dissector is available in the latest version of our plugin, which can be accessed from the SAP-Dissection-plug-in-for-Wireshark repository. We welcome any type of contribution, from improvements to bugs and issues. Feel free to report them via GitHub!
Crafting Packets at Will
Now that we have tools to dissect traffic between HANA clients and servers, let us look at how to craft and send packets using the protocol. As already mentioned, there might be multiple reasons why you might want to manually craft packets instead of using the official tools. From an assessment perspective, it can be useful to automate identification of configuration patterns in large landscapes, validate if patches for known vulnerabilities are properly applied, and so on. From a security research and vulnerability hunting standpoint, it can help to spot logic or architectural flaws in the protocol, or apply custom mutation routines to perform remote fuzzing, and more.
We added a new custom layer to our well-known Open Source library pysap. The documentation and the examples in the code repository can provide an overview of what can be achieved by the library. Finally, documentation provides a view of the different packet types and how those can be constructed:
Along with the packet layer added, we included a couple of example scripts that illustrate how the library can be used and implemented creating a couple of interesting scenarios. Adding functionality such as the one exploited in the infamous SQL Login Remote Code Execution vulnerability (CVE-2015-7993) or the more recent CVE-2019-0350 should be easy using the new layer and the example code as a base.
HANA Tenants Discovery
The first example is a mechanism that HANA incorporated as a way for clients to discover where to connect in multi-tenant deployments. The impact of this from a security standpoint is minimal, as the only information provided is whether a given database name is connected or not to the HANA services and in some cases the IP address and TCP port of that tenant. But it will help us illustrate how the library can be used to manually craft and send packets.
HANA 2.0 version SPS 03 introduced support for this discovery mechanism, using the DBCONNECTINFO Part kind. Obviously, this needs to be performed pre-authentication as it is used by the client to know what IP address and port it should use to connect to the proper tenant database. Sending a discovery request in pysap is as easy as running the following lines of Python code, in this case using 192.168.1.136 and port 39013 as our target SYSTEMDB database tenant:
In : from pysap.SAPHDB import * In : hdb_dbconnectinfo_options = [SAPHDBOptionPartRow(key=1, type=29, value="HXE")] In : hdb_dbconnectinfo_part = SAPHDBPart(partkind=67, buffer=hdb_dbconnectinfo_options) In : hdb_dbconnectinfo_request = SAPHDB(sessionid=0, segments=[SAPHDBSegment(messagetype=82, ...: parts=[hdb_dbconnectinfo_part])]) In : conn = SAPHDBConnection("192.168.1.136", 39013) In : conn.connect() In : conn.initialize() In : conn.send(hdb_dbconnectinfo_request)
The server will reply denoting if the database name specified in the request is available and connected to the master index server, and the location of it (hostname or IP address, and port):
In : response = conn.recv() In : response.show() ###[ SAP HANA SQL Command Network Protocol ]### sessionid = 0 packetcount= 0 varpartlength= 72 varpartsize= 29968 noofsegm = 1 packetoptions= Uncompressed reserved1 = 0 compressionvarpartlength= 0 reserved2 = 0 \segments \ |###[ SAP HANA SQL Command Network Protocol Segment ]### | segmentlength= 72 | segmentofs= 0 | noofparts = 1 | segmentno = 1 | segmentkind= Reply | reserved2 = 0 | functioncode= NIL | reserved3 = 0 | \parts \ | |###[ SAP HANA SQL Command Network Protocol Part ]### | | partkind = DBCONNECTINFO | | partattributes= 0 | | argumentcount= 3 | | bigargumentcount= 0 | | bufferlength= 26 | | buffersize= 29928 | | \buffer \ | | |###[ SAP HANA SQL Command Network Protocol DB Connect Information ]### | | | key = 4 | | | type = BOOLEAN | | | value = no | | |###[ SAP HANA SQL Command Network Protocol DB Connect Information ]### | | | key = 2 | | | type = STRING | | | length = 13 | | | value = '192.168.1.136' | | |###[ SAP HANA SQL Command Network Protocol DB Connect Information ]### | | | key = 3 | | | type = INT | | | value = 39015
In this example, by means of this discovery mechanism we learned that the HXE tenant database is available at the IP address 192.168.1.136 and port 39015. An example script is provided to automate all the processes and provide a consumable output with the results. Given a list of tenant database names, it will go through all of them trying to see if each tenant name is available in the target database.
HANA Database Authentication 101
The HANA database, and the underlying protocol, supports a wide range of authentication and Single-Sign On mechanisms that have been added over time. In the current version (2.0 SPS 05), the following are the documented methods:
- Password-based authentication, with the following Salted Challenge-Response Authentication Mechanisms (SCRAM):
- Kerberos, via Simple and Protected GSSAPI Negotiation Mechanism (SPNEGO).
- Security assertion markup language (SAML).
- SAP’s Logon and Assertion tickets, which is specially used for integrations with SAP Web Application Server or SAP Portal instances.
- X.509 client certificates, which can be configured to provide mutual authentication.
- JSON Web Token (JWT).
- An external LDAP directory server.
Authentication to the database is implemented with a series of particular messages that include the AUTHENTICATE kind. The general process is described in the following diagram:
As can be observed, the overall idea is that the client and the server exchange a series of events in some sort of “handshake” that might involve multiple packets and round trips depending on the method in use. As part of the last round trip, the client sends a final CONNECT request message that is replied to by the server establishing the session and handing over an identifier. The established session is only tied to the communication channel between the client and the server, but there is no strong cryptographic binding mechanism to enforce it. Moreover, in certain authentication methods such as SAML, the client obtains session “cookies” that can act as bearer tokens and be reused in further connections to the server without the need to re-authenticate.
One particularity is that AUTHENTICATE request messages can contain information concerning more than one authentication method, and the server is in charge of replying and continuing the handshake with the one it chooses or prefers.
Securing and researching communication paths requires a good understanding of each protocol’s inner workings. At the time of conducting vulnerability research, troubleshooting networking issues or just making educated decisions about protection mechanisms and security levels, having tools to practically dissect and craft network packets is a must have. In this blog post we shared the basics of our recent developments for adding support of the HANA SQL Command Network Protocol to our exploration Open Source tools on SAP security. With the understanding that this article served as an introduction, we hope to share more insights about this protocol and the different authentication and security mechanism in future articles!
Read the complete posts in this series: