This is a write-up for the recently retired Waldo machine on the Hack The Box platform. If you don’t already know, Hack The Box is a website where you can further your cybersecurity knowledge by hacking into a range of different machines.
As opposed to the more generic two-stage boxes, Waldo was unique in that there were three challenges to overcome, and each had completely different methods needed to do so. Whilst the third stage was a little tedious and hard to explain, I learnt about some small Linux functions that I never knew existed before.
PART ONE: USER
The usual nmap scan reveals three open ports:
Seeing as the SSH protocol is fairly up-to-date (and there are very few sun-answerbook enumeration tools), we can assume that this will be a web application attack.
When visiting the website, we are shown a (very gross) list manager:
As shown in the gif, we have a few different functions:
- View all lists
- Add/rename lists.
- Open a list to view its contents.
- Add/rename an item in a list.
- Delete list items.
- Delete lists.
With this in mind, let’s take a look at some of the requests in Burp Suite.
Attempting to open up the first list produces this request:
And, similarly, attempting to open up a list (within the first list) produces this request:
We can see from this that we are querying the dirRead.php and fileRead.php pages, with the file parameter being posted. Since we are looking for a way to get into the system, attempting directory traversal to find important system files through LFI seemed like a good idea.
As such, I tried performing simple directory traversal on the dirRead.php page, which showed us the following:
As shown, we now have access to all files in the above directory. Let’s now try going back another directory, so that we can access more sensitive files:
Okay, so it seems that we can’t traverse back any more. We can assume that some form of input sanitization is taking place, and so we can try some simple bypasses. After only a couple of attempts, I found this, which outlines a method where we can bypass the input sanitization by using “…/…//”, instead of “../../”:
We now have successful directory traversal! As such, we can swap over to fileRead.php requests in order to read the contents of files:
Since this process of changing directories is a little tedious, I wrote a script to help us explore the file system. While this is completely pointless and genuinely a huge waste of time, I did it anyway (I guess I have too much free time?).
I’m not going to go over the code, but it essentially lets us use cd, ls and cat to explore the filesystem. Since we want to upgrade to a “proper” shell, let’s go and find the user’s SSH key.
Sidenote: Whenever I am in a situation where we have read-only access to a system, I refer to this article, since it outlines many important files.
We now know that the user is called nobody, and we have their relevant SSH key (although we could have found this through /etc/passwd anyway). With this in mind, we can SSH in, and obtain the user flag:
PART TWO: ESCALATION
This next part was difficult, as I didn’t know what to look for. I ran the usual enumeration scripts, and looked through open ports/SUID files, however found very little.
Eventually, I decided to just list all files created by waldo, so that I could comb through them to find any useful information:
waldo:~$ find / -user $USER ! -path "*proc*" ! -path "*var*" ! -path "*dev*" 2>/dev/null/home/nobody/home/nobody/.ssh/home/nobody/.ssh/known_hosts/home/nobody/.ssh/.monitor/home/nobody/.ssh/authorized_keys/home/nobody/.viminfo/home/nobody/user.txt
You can find a breakdown of this find command here.
From this, the .monitor file sticks out, since it isn’t a regular .ssh file. Upon opening, we can see that this is another SSH key:
We can assume that this is a key for a user called “monitor”, and as such we can SSH back in as this user:
Unfortunately, there was still more to do before we could fully act as this user.
As shown, we’re actually in an rbash (restricted bash) shell, which meant that our actions were extremely limited. I checked out GTFObins to see if rbash was exploitable, but it wasn’t there.
Let’s just run this command:
Since we can now cd, it seems like we have escaped the shell!
PART THREE: ROOT
I later learnt that this was not the only way to escape this shell. By directing the SSH traffic through netcat, we can choose the shell we want. As such, we could then catch the shell, and specify our shell type as bash. If this doesn’t make any sense, take a look at this gif, which goes over this process:
Although this method wasn’t necessary, it’s still a good thing to note for future boxes.
Now that we have a shell, let’s look around the filesystem. The first two folders that we are presented with are app-dev and bin.
monitor@waldo:~$ lsapp-dev bin
The bin folder contains the binaries that we were allowed to use before, and so there’s little use enumerating that further. However, the app-dev folder is full of interesting files:
Let’s begin by taking a look at the source code for the logMonitor program, which seems to be logMonitor.c:
I’ve redacted large repeated parts of this file to save space.
We can gather from this that the script is used to read out the contents of various log files in the system. However, from what I can tell, this is pretty secure.
Let’s now try running this script to view some logs:
monitor@waldo:~/app-dev$ ./logMonitor -hUsage: logMonitor [-aAbdDfhklmsw] [--help]monitor@waldo:~/app-dev$ ./logMonitor -aCannot open file
It looks like we don’t actually have the correct permissions to view these logs.
After messing around with this file for a bit, I decided to explore the v0.1 directory:
Here we see a separate logMonitor program, with slightly different permissions than the other. Let’s now try running this, and search for some logs:
So, this script has permission to read the logs, whereas the other script doesn’t!
Let’s take another look at the separate file permissions:
Despite the write permissions being different, the others all look the same. I then checked the permissions for the v0.1 directory, but those seemed pretty normal too.
It was at this stage that I spent a few hours trying to figure out just how this file has the permission to actually run. There was so SUID trickery going on, and no strange inheritance permissions.
Eventually, I came across a brief mention of file capabilities, which is a way of setting very precise permissions on a certain file. These are often used as a more secure version of SUID, as more delicate control is given to the file. This sounded plausible for us, and so I checked the capabilities of the binaries like so:
We can see here that the logMonitor-0.1 file has the cap_dac_read_search capability, which allows it to read/search all files on the system. The “ei” flag then the capability is (e) effective (as in currently active) and (i) gives this permission to any child processes spawned.
The inheritance flag looked interesting, and so I tried unsuccessfully to force the binary to spawn another binary (that we control) as its child.
I eventually decided to have a look for any more files with similar capabilities:
It looks like tac has the same capabilities as logMonitor-0.1!
If you don’t already know, tac has the same functionality as cat, but reads through files line-by-line backwards. Therefore, we should be able to use it to read the flag:
And with that, the box has been completed!