Every now and then, an regular penetration test project can take a decidedly irregular detour into the land of zero-day exploits. In October 2017, I discovered a zero-day vulnerability in Ulterius, a widely used, open-source remote access software.
Come along. I have a zero-day I want to show you.
What Weird Ports You Use
I started my testing running a typical set of vulnerability scans in Nessus. The scanner detected a possible directory traversal vulnerability on one of the client’s web servers. This web server was running on port 22006, which is an unusual port for a web server. Web servers on weird ports are always worth a look.
I browsed to the base URL to check out the application. The following app greeted me:
Hmmm, a remote access application. At this point, I was not familiar with Ulterius. I had seen it a few places, but this was my first time pentesting an installation.
After connecting to the server, a login page was displayed with a username in the login field. Perhaps that is a valid user name?
The next move is research. I did some Googling. Ulterius is a web-based remote access software. It runs on Windows systems. It provides flexible web-based remote access. Two developers maintain the code, and have an active GitHub, website, and Twitter account. It is like thousands of other open source projects out there. A free, handy tool with broad usage.
This sounds juicy.
I did not have a valid password for the admin account, of course, so I turned back to the directory traversal finding. Nessus claimed that the following URL was a working example:
I pasted it into my browser and, sure enough, I immediately got the server’s win.ini file. That certainly validates Nessus’ finding.
I searched around the Internet and found no mention of this vulnerability anywhere. It was looking like I was the first one to discover it. Cool! A zero-day exploit! Those are always fun to uncover. It is what penetration testing is all about.
But, wait…how serious is this vulnerability? Can I do anything with it?
Down the Rabbit Hole
I had the ability to download arbitrary files, but what files do I want and where are they on the system? With almost zero knowledge about this server, I could be fumbling around forever.
However, Ulterius is a freely available application. As such, I downloaded my own copy and installed it on my own Windows server. I figured maybe I could download a password file or other Ulterius configuration files that might help me gain access to the system.
After the installation, I discovered that I could indeed download an Ulterius config file, but it did not reveal much. I knew the Ulterius install path and a valid username on the system, which was the same as the username Ulterius already gave me. There was no password configuration file either. Ulterius uses the user’s Windows credentials.
Then I noticed a file called “fileIndex.db”. What do you do?
I had already logged into my own Ulterius server and played around with it. It has a feature that lets you browse and manipulate the Windows file system and search for files. I had a feeling that this fileIndex.db file might contain an index of the searchable files. I loaded it up in Notepad++ and here’s what I saw:
Bah! That is not helpful. If it was a searchable file index, I could not easily read it. Maybe it used some compression or encryption. I contemplated pounding on that for a while. However, that could be a real time sink.
The only tool that I know can read this file, is Ulterius itself.
Oh! Of course! If It had been a snake it would have bit me.
Just swap the files! I quickly downloaded the client’s fileIndex.db file and then replaced the fileIndex.db on my own server with the client’s file. BAM! I could now search the client’s file system using my own Ulterius server!
Using this new information, I was able to search the client’s file system for file names containing juicy keywords like “config,” “user,” and “password.” With this type of information, I could potentially identify and download all kinds of sensitive files on the system. I actually found some KeePass database files, as an example. This directory traversal vulnerability was a goldmine for hacking.
Just the Beginning
When the penetration test project was over, I decided to throw together some code to make it easier to exploit this vulnerability in the future. This way, if I encountered this again, I would not need to setup a whole new Ulterius box in my lab. Furthermore, I could automate the exploit. Super fun.
The first thing I had to crack was how the fileIndex.db file was constructed. Since Ulterius is open source, I downloaded the source code and picked it apart.
After a little reverse engineering, I found the following in DatabaseManager.cs:
The most interesting item in the code is an object called DeflateStream using “CompressionMode.Compress.” Initially, I assumed this meant the file was compressed. Compressed files are much easier to manipulate than encrypted ones. I did a bit of Googling, and my assumptions were confirmed.
Ulterius uses gzip to compress the file index. Using additional sources I found online, I cobbled together a python script that decompressed fileIndex.db. This was a solid first step, but the output was not searchable or human readable:
Decoding the Mysteries of fileIndex.db
The more I looked at this output, the more something seemed odd. Ulterius was not merely dumping a list of files, there was something else in here.
I dumped the output into xxd to see what the hex looked like:
The file has file names and paths as well as some other unknown data. Every so often, there are a bunch of \xff bytes as well. I tried using regex to remove the bits between the paths and the file names, but that was a dead end. I went back to the source code to investigate further.
I spent some time tracing the steps. The code loops through all the drives on the system, then loops through every file on each drive. Next, it writes the following information to the fileIndex.db file in this order:
- Length of the file name
- File name
- Length of the file’s directory path
- File’s directory path
- Size variable (always -1 for some reason)
Things were beginning to make sense. The first few bytes in the file are a dateTime object. Those are not necessary for an exploit, so I can strip them away. Those weird bytes in between the file names and paths were the lengths of each field. The \xff bytes were the “-1” that the code always sets to the size field. I assume the size field is not used at this time, so it is always set to -1.
This gave me enough information to decode the data and output a list of files without all the other junk.
Automating the Decode
After decoding this key file, I was ready to build an automated decoder. This program had to do the following:
- Decompress the fileIndex.db file
- Strip away the first eight bytes (dateTime) of the output
- Obtain the length of the next file name
- Read the next file name
- Obtain the length of the next file path
- Read the next file path
- Put the path and the file name together
- Output the path\file to stdout
- Jump back to step 3 (unless we are at the end of the file)
After a little trial and error, I hammered together a solid script:
Now with an automated decoder built, the next step was to integrate that into an automated exploit script. This way, if I run across this vulnerability again, I can quickly test it.
Writing Exploit Script
This exploit script has two main functions:
- Automatically download, decompress, and decode the fileIndex.db file for me
- Retrieve a specified file
I put together a Python script to do this. Here’s an example of the index download and decode function:
Here is an example of retrieving one of the files from that fileIndex.db output:
If you want to check out the code, you can find it all on my GitHub page.
I was surprised how long this vulnerability had gone undetected. Ulterius has been around for awhile, and is a widely used remote access technology. However, this is why testing environments and third party applications is so important. Even if those applications are widely used, there may be lurking vulnerabilities inside the code.
Responsible Disclosure Notice
Anitian is committed to responsible disclosure of any vulnerability we discover. When I discovered this vulnerability, I immediately contacted the developers via Twitter. The developers responded quickly and asked for details. After exchanging research, the developers confirmed the vulnerability and started working on a patch.
Less than three days after I notified the developers of this vulnerability, they issued a patch and notified the users. This was outstanding. Anitian complements the quick, responsible actions of the Ulterius team. If you use Ulterius in your environment, make sure you upgrade all your installations to the latest code, available here: https://ulterius.io/
The team asked us to wait a few weeks to disclose our research. We are honoring that request and this blog was published three weeks after the patch and with the consent of the developers. Below is a timeline of the disclosure:
- 10/20/2017 – Notified the Ulterius development team
- 10/20/2017 – Response from developer confirming vulnerability
- 10/23/2017 – Vulnerability patched
- 11/13/2017 – CVE Assigned (CVE-2017-16806)
- 11/30/2017 – Vulnerability disclosed publicly (exploit released)