Advisory and Exploitation: The MELAG FTP Server

Intro

During an engagement in early 2021 my colleague nv1t and myself stumbled across an FTP server with a banner that we've never seen before, which said MELAG FTP SERVER along with a version number.

Melag FTP Server SYST Banner

As this banner was unknown to us and the existence of an FTP server at the specific network location itself seemed a little odd (since we did not expect to see an FTP server on the external network of this client), we decided to take a look into what this piece of software is and what we could find about it. Querying Google for the presented Banner, we found the source of this FTP Server and the company that had developed this with the first hit. Searching for known vulnerabilities, however, did not reveal any results. Luckily for us though the vendor did offer this exact FTP Server in the same version as we found it in our client's network for download.

We downloaded the FTP Server, set up a testing environment, began to dissect it and found 6x high impact vulnerabilities.

Summary and Mitigation Advice

In the following sections we will describe an attack chain that allows an attacker to escalate from an unauthenticated network position to gain authenticated host access, which could further be exploited to compromise and control the targeted host system running the vulnerable FTP server. This attack can as well be conducted from the internet against publicly accessible MELAG FTP server instances. After a long and fruitless disclosure process (see the following timeline) we decided to disclose our findings publicly, to allow affected organizations and companies to be aware of the vulnerabilities and protect themselves against attacks.

To mitigate exploitation of these attack we advise to disconnect MELAG FTP servers from untrusted (public) networks, especially from the public internet. While writing this blog post, the vendor has so far not provided any software update to mitigate the identified vulnerabilities, therefore the only mitigation against exploitation is preventing network level access to this FTP server.

The vulnerabiliy research detailed in the following sections has been conducted by my colleague nv1t and myself, as part of our role at SSE, during the aftermath of a client engagement.

Timeline

  • 27.05.2021: Initial Mail to MELAG informing about the found vulnerabilities
  • 07.06.2021: Response from MELAG, details and report were handed over to MELAG
  • 08.06.2021: Confirmation of Report received from MELAG
  • 12.07.2021: 1st Update request from SSE to MELAG, asking if there are any questions on the report or update plans - no response
  • 12.08.2021: 2nd Update request from SSE to MELAG, auto response indicating absence of contact - no further response
  • 20.09.2021: 3rd Update request from SSE to MELAG - no response
  • 20.09.2021: CVE Request to MITRE for 6x identified vulnerabilities, confirmation of submission by MITRE
  • 06.12.2021: 1st Update request from SSE to MITRE, asking if there is any update on the process - no response
  • 18.02.2022: 2nd Update request from SSE to MITRE - no response
  • 04.04.2022: Vulnerability information submitted to CERT-Bund (BSI) - Confirmation of submission by CERT-Bund
  • 25.04.2022: 1st Update request from SSE to CERT-Bund (BSI) - Response on 26.04.2022
  • 25.04.2022: Informed MELAG and CERT-Bund (BSI) that this blog post will be published during the next two weeks. - Response on 26.04.2022
  • 26.04.2022: CERT-Bund (BSI) confirmed the vulnerabilities and will contact MELAG - No statement from MELAG as of 05.05.2022.
  • 05.05.2022: Public Disclosure, up to this point the software has not been updated and MELAG has not responded.

Vulnerabilities

In the following sections the identified vulnerabilities will be described. Please note that these vulnerabilities will be described in order of a potential exploitation chain, not in order of their rated risk.

In total we identified the following 6 vulnerabilities:

  • User Enumeration
  • Authentication Bypass
  • Path Traversal
  • Storage of Cleartext Passwords
  • Weak File Permissions
  • High System Privileges

The FTP Server was found to be written in .NET, which allowed us to decompile and analyze the source code. dnSpy was used for this purpose. Snippets of this source code will be shown in the following sections to highlight the vulnerable code functions.

User Enumeration

As an entry point into the application, we found a user enumeration vulnerability that allows an attacker to identify whether a given username is a registered FTP user or not. As with all user enumeration vulnerabilities, the vulnerability presents itself by returning different server response for valid and invalid usernames. The FTP protocol defines the command USER to submit the username used for logon, which is vulnerable to user enumeration, as shown below:

User Enumeration Vulnerability

User Enumeration Vulnerability

This vulnerability could easily be exploited using a brute-force style approach using an automated network scanner, such as hydra or by building a custom enumeration script.

As an example: Using a naive python-based network scanner the 10.000 name samples from SecLists could be tested in about 3mins on a local network.

User Enumeration Exploitation

User Enumeration Exploitation

This user enumeration vulnerability within the USER command function can also be found in the application .NET code, as shown below:

Source code: USER Command

Source code: USER Command

Authentication Bypass

Given a valid username we digged deeper into what happens within the implementation of the USER command in case a valid username was submitted, which is shown below:

USER Command: Valid User

USER Command: Valid User

The important bit here is that the RefUserAccount attribute of the cc (ClientConnection) variable is set to the account that matches the given username if the identified account is active. To get a better picture of what this means the server UI, which comes with the installation of the FTP server, is shown below:

FTP Server UI

FTP Server UI

This interface shows the identified user "ftpuser" along with a checked "active" box, showing that this FTP user is currently active and allowed to log in.

The interesting takeaway from the code snippet above is that the RefUserAccount attribute has been set for the connection, although no password has been specified yet. So far only the USER command has been sent to submit the username. This gets interesting when inspecting other command implementations, for example the implementation of the LIST command that is shown below (snippet):

Source code: LIST Command

Source code: LIST Command

This source code snippet shows the implementation of the FTP LIST command, which can be used to list the contents of the current directory. As highlighted above this command used the RefUserAccount attribute of the connection to resolve a user's base directory. The only requirement to make the highlighted call successful is that the RefUserAccount attribute is set, which has been previously set by submitting a valid username. What's missing is any form of authentication verification, as no password has been provided for this user so far. Looking at this code we were curious if any FTP functions could be called by only submitting a username, but no password. Testing this theory resulted in the following output:

FTP List Command Without a Password

FTP List Command Without a Password

The server response shows a "Login failed", however the dir command seems to imply that the command was successful, although no output was received (We'll go into the details of this behaviour at the end of this section...). This result let us into trying this manually and opening up a data connection ourselves (using the FTP passive mode).

Manual FTP LIST Command

Manual FTP LIST Command

Using the FTP PORT command we were able to specify our own endpoint for the passive FTP mode and successfully retrieved the directory listing of the user ftpuser without specifying any password for this user. Looking through the rest of the code, we were interested if this flaw is only present in the implementation of the LIST command. We found that this flaw was present in all implemented FTP commands, which also allowed us to read the file "myfile.txt" that has been identified earlier using the FTP RETR command:

Manual FTP RETR Command

Manual FTP RETR Command

Now that we proved that this vulnerability can be exploited, let's investigate why the dir command did not returned any output when used from within the ftp command line tool. The reason for this is that the ftp command line tool - like many other ftp clients - will always send a password with the PASS command to the ftp server, even when this password is empty. In other words: Every ftp client expects the server to process a USER command followed by a PASS command. Looking at the source code of the MELAG FTP server for the PASS command, we can find the following snippet:

Source code: PASS command

Source code: PASS command

If the refUserAccount variable is set - which it is in our case, as we send a valid username with the USER command, but the password does not match with the password of the associated user, then cc.RefUserAccount will be set to null. Looking at the source code for the LIST command, which is was is triggered when the command dir is sent through the used ftp client, we'll see that a response with the status code of 150 FileStatusOK is send back to the client (which we also saw earlier) and then the cc.List is called to handle the directory listing with the first argument of cc.RefUserAccount.BaseDirectory.

Source code: LIST command revisited

Source code: LIST command (revisited)

Since the cc.RefUserAccount is null, BaseDirectory is called on null, which causes an error and the termination of the command. We'll add another annotation to this at the end of the blog post.

Path Travesal

So far we were able to "authenticate" to the FTP server by only using a valid and active username and reading a user's base directory indluding all files therein. Our tour through the code and the various implemented FTP commands also revealed that the application is vulnerable to path traversal attacks, which we found within the implementation of the CWD command.

Source code: CWD Command

Source code: CWD Command

This source code snippet shows the ChangeDir command that is called when submitting the CWD <PATH> command. The supplied sub-path of the CWD command is passed as the 2nd argument ("subDir") to the ChangeDir function. As highlighted above no sanity checks are performed to ensure the user is actually supplying a "sub directory", which allows an attacker to traverse through the entire host system, as shown below.

CWD Path Traversal

CWD Path Traversal

Consequently, this allows to read arbitrary files of the host system, as long as the user who is running the FTP server has the permission to read these files (which we'll later see could be all files). A proof of concept is shown below:

PoC: Reading C:\Windows\win.ini

Proof of concept: Reading C:\Windows\win.ini

Storage of Cleartext Passwords

Being able to read through all files (that the user running the FTP server has permission to read) allowed us to look for potentially interesting configuration files that ship with this FTP server...and we found one.

The FTP server stores configurations in an XML file called "config.dat", which is stored under %ProgramData%\ProgramData\MELAG Medizintechnik GmbH & Co. KG\FTP-Server\config.dat. Looking into this file we found - among other configuration settings - ftp user accounts with their respective password stored in plaintext:

Clear Text Credentials

Clear Text Credentials

Although so far we did not need to know the ftp user's password to run any of the above attacks it's certainly not good having these passwords stored in plaintext on disk.

Weak File Permissions

So far we had to specify that combining the authentication bypass and the path traversal attacks allows an attacker to read arbitrary files (and directories) on the target host, only if the user running the FTP Server had sufficient (host-level) permissions to read those files. We found this caveat does not apply to the sensitive config.dat file, which stores ftp user credentials in plain-text, as the default installation of the FTP server allows Everyone full control over this file

Weak File Permissions

Weak File Permissions

This would also allow a local attacker on the host system to compromise all FTP users and their files, as an attacker can read (and change) all FTP users credentials and thereby login as any user.

High System Privileges

Lastly to weaken the "we can only read/write files that the user running the FTP server has permissions to read/write"-disclaimer even more we found that when installing the FTP server, the administrator is prompted with the following installation choices.

FTP Installation UI

FTP Installation UI

If the user chooses to install the FTP server "as Windows application" the server is installed like any other application and can be started by any user. If the user on the other hand chooses to install the FTP server "as Windows service", a service is created that runs the "NT Authority\SYSTEM" user, which has the highest system privileges.

FTP Server running as System

FTP Server running as System

A compromised MELAG FTP Server running as "SYSTEM" could then be used to compromise the entire host system.

Further Annotations

When describing the "Authentication Bypass" vulnerability, we found that the default Linux ftp command line client does not allow us to exploit the identified vulnerability. During our research we figured that many ftp clients, including Python's default ftplib, behave in the same manner of sending the PASS command right after the USER command, disallowing a user to step in without a password being send. During our analysis we patched the default Python ftplib to serve our needs, but for this blog post we figured it's worth noting that the "manual" approach, going through the protocol step-by-step, can also be fruitful.

Another interesting, but not exploitable (at least as far as we know) twist worth mentioning can be found in the following screenshot that was previously shown in the "Authentication Bypass" section:

Source code: LIST command 3

As mentioned earlier this code does not check for an authenticated user session, but for our exploit a valid username was required. This requirement is only made necessary, due to the fact that in .NET calling an attribute of a null object causes a run-time exception. If .NET would evaluate a call on null to an empty string, we could have exploited this FTP server even without a valid username...

Conclusion

During our research we found several vulnerabilities within the MELAG FTP Server in version 2.2.0.4, which allows an attacker to chain some of these vulnerabilities to escalate privileges from an unauthenticated network position to the highest system privileges on a target host.

We think that these vulnerabilities are pretty severe, especially given that these vulnerabilities can be chained and that this vulnerable FTP server is - due to the market position of the vendor - likely to be found within companies of the medical business sector, such as hospitals, medical practices and so on.

We would have preferred to close all of these vulnerabilities with the vendor, but sadly we didn't receive any response, even after almost a year after we handed in our report describing all of the presented issues. However, we still are and always will be happy to support the mitigation process against the shown attacks.

Carsten Sandker
Carsten is part of our Offensive Security Team, helping our clients identify vulnerabilities and preventing attacks. He is specialized in Active Directory security and scenario-based attacks.