This blog post is about a previously unknown critical vulnerability in the Austrian electronic banking application ELBA5. The issue discussed here could be abused to gain full control over any ELBA5 database server as well as the underlying operating system. It has a confirmed CVSSv3 score of 10.0.
What is ELBA5?
ELBA5, as shown below, is one of Austria’s most important business-focused electronic banking applications. It is used by the finance departments of many large organisations and supports about 24 different banks.
It is important to note that there are two distinct ELBA5 releases, namely: ELBA5 single-seat and ELBA5 multi-user (aka network installation). The vulnerability discussed here is only exploitable for the ELBA5 network installation. However, I have also reported several other, although less critical issues for the single-seat release. So it’s highly recommended to updated to the latest version anyway.
To give you a broad understanding of how the ELBA5 software stack works in a multi-user configuration, I create the following diagram. On the left side there is the ELBA5 server: This machine has two distinct functions: On the one hand it serves the ELBA5 binary application to all clients using a standard Windows file share. On the other hand it provides the ELBA5 backend, which is basically a SAP SQL Anywhere Database.
The enduser systems simply connect to the mentioned file share and launch the ELBA5 client from there. This makes it easy to update the application, as there is only a single package that is used by everyone. All the data that is viewed, modified or created from within the ELBA5 client is directly stored into the backend database. This is everything you need to know in order to understand the following exploit…
How everything started
The story of this vulnerability began during a penetration test last year. There I was able to gain access to the finance department’s terminal server. Amongst other’s they also used the ELBA5 network installation for their daily business. As I’m curious by nature I immediately launched all the interesting looking applications. Below is an image illustrating the sequence of things that happened right after. Can you spot the (possible) issue?
Well, here is the thing that caused my attention: How is it possible to install automatic updates without any previous authentication? Is the ELBA5 application using hardcoded credentials to connect to the backend service?
With this initial discovery I started to dig a little deeper. As ELBA5 is developed in Java I used the CRF decompiler to learn more about the inner workings of the application. Strangely, I could not really find any code that established the connection with the database backend. At that point I got really interested…
As my first try failed, I switched to a more brute force-like method: As I guessed that the ELBA5 client uses hardcoded credentials, they have to be somewhere in memory. A quick search for strings like user, uid, password, pwd however did not reveal anything interesting. Hence I thought, these credentials may get cleaned up immediately after establishing the initial connection. This is where the brute force part comes into play: I downloaded Microsoft’s procdump and took memory dumps as fast as I could while launching ELBA5. As shown in the screenshot below, this worked out. I was able to capture the credentials of not one, but two valid backend users. Namely, “connector” and “elba”:
By setting up a second ELBA5 network installation, I verified that the connector user always uses the same static password, whereas the elba user’s password did not work there. This was a problem as only the elba user holds administrative DBA privileges. Based on what I had learned already I came up with the assumption that there has to be a two step process for authentication:
The 1 Million Dollar Question: How is this working in Detail?
After taking a closer look at the privileges of the “connector” user on my debug machine (where I knew the DBA password), I discovered that this account is only authorised for a single column in a single table. Well, now I knew where the encrypted DBA password was stored. That it is encrypted (or at least obfuscated) was clear after I compared the content of the daten column with my known elba password. They were completely different.
So, I again had to take a closer look at the source code of the application. Finally, after many hours of debugging I discovered an interesting comment:
Has the database logic been “outsourced” into a separate library? To get a first glance I extracted all the strings from the systemtools.dll library… Some stood out immediately:
The highlighted SQL commands in the above screenshot are likely used to decrypt the secret elba DBA database password. Presumedly the AES encryption algorithm was used to secure the password. From the static strings alone however, I was not able to exfiltrate the required password. So I had to switch to something more dynamic: Immunity Debugger.
After setting an access breakpoint on the memory addresses of the above strings (and a few hours of debugging), I found the following information on the stack. The highlighted part contains the hardcoded key that is used to decrypt the elba user’s password.
Bringing it all together
By combining what I had learned by now, it was possible to reliably gain DBA permissions for every single ELBA5 network installation:
- Connect to the database with the hardcoded “connector” user and SELECT the AES encrypted DBA’s user password
- Decrypt the password with the static AES key, as obtained with the help of Immunity Debugger
- Connect to the database with the user elba and the decrypted password. We now have full control over all information that is stored in the DB.
However, this was where the real fun began…
Adding a Backdoor User
As I was targeting a banking application I thought it would be great to earn a bit of extra cash. So, what about adding a backdoor user?
After again analysing the source code I found out how the user’s password is stored in the table “BEDIENER”:
By analysing all the involved methods, I was able to make it more readable as:
This finally made it possible to remotely add arbitrary users to the ELBA5 installation. Logically with admin permissions:
Because everyone wants to have a user called “HACKER” in this electronic backing application – Right?
Remote Code Execution
But wait, there is more. Because from a pentester’s point of view we care more about overtaking a server than stealing money…. Luckily there is an old friend in the ELBA5 SQL Anywhere database server that we can use: xp_cmdshell. This SQL command can be used to run arbitrary applications on the operating system level. What makes this even more interesting was, that the database runs with full SYSTEM level permissions:
That means, we can also add a new Windows Admin. This give us full control over the affected server. Mimikatz anyone?
To automate the process discussed in this blog post, I wrote a fully fledge python exploit. It can either be used to add a new ELBA5 user to the database or remotely run a command with SYSTEM permissions on the target system. The only thing that is required is that the ELBA5 SQL Anywhere Database service is running a vulnerable version and is accessible over the network (TCP port 2640).
You can download the full exploit here:
Coordinate Public Disclosure Process
I also want to briefly discuss the coordinated public disclosure process that I went through with the developers of ELBA5. The initial issue was reported last year and triaged within days. As some may have already guessed, this is more an architectural issue and so it required intense rewrites and testing. I was invited twice during this process to discuss the current state. We openly talked about the risks and how they can be mitigated.
I really want to everyone involved for how professionally this matter was resolved. Not many companies take IT security that serious. It really shows how they values their partners and endusers. THANK YOU!
This coordinated process is also important for endusers. Why? Well, because the only thing they have to do is: Please install the lastest ELBA5 5.8.1 release from https://www.elba.at. A lot of testing went into making the transition to the new authentication module completely transparent.
As I always think it is important to summaries the key aspect, I created the following overview. It gives a great high level introduction into the underlying vulnerability and the suggested solution. This slide is also available in German.
If you have any questions, please contact me directly at firstname.lastname@example.org or use the comment form below.
Thanks for reading that far 😉