Hack the Box has finally retired Jail! Jail is a really
fun box with a consistant level of difficulty all the way through, and a really fun
ending.
There is some interesting stuff to parse through here (nfs), but lets just start by scanning the HTTP port.
Nothing interesting, but persistence is key when enumerating. While dirb and its defaults are great for quick and dirty scanning,
it will often miss things a larger list would catch. So the next step is to bust out the big guns: dirbuster or gobuster. Using the directory-list-lowercase-2.3-medium.txt list from dirbuster, we hit the jackbot, the jailuser directory. This contains some source
code, a build script, and the resulting binary. After looking at the source code briefly, it looks like this is the service listening
on port 7411:
It’s pretty clear that this code is vulnerable to a simple buffer overflow. handle calls auth
and passes in username and password, both of which are 256 byte arrays. In auth, however,
password is copied into a 16 byte array, meaning we have 256 - 16 bytes of overflow. Since we’re
calling this binary remotely, we need to execute some code which connects back to us, or binds a port
which we can then connect to.
The next step is determining exactly how we execute this code. Luckily for us, the binary is compiled
with an executable stack:
This means we can simply overflow the array with shellcode, and don’t have to worry about searching for
any ROP gadgets.
So, we know what kind of shellcode we need, and how we can load it into memory. The final step is determining
where to jump to. This presents a slight challenge to us, as the binary does have PIE enabled. That means the binary runs
at a random(ish) address every time it starts.
Once again (how coincidental :)), this binary presents an easy way around the challenge. If we set debugmode (by sending “DEBUG”) and try to authenticate, it will tell us where the buffer is located. Now that we have all the pieces we need,
lets get pwntooling
First, lets import pwntools and set our context:
Next, we need to connect to the remote service:
One of the many awesome things about pwntools is that it can do a lot of the annoying shellcode work for us. It has a
module called shellcraft which has architecture specific
shellcode for common needs. In this case, we want to find an open socket and open a shell on it, and then jump into
that shellcode (address of buffer plus an offset into our NOP-sled):
Finally, we calculate the final payload, and send it:
Step 1: complete. Unfortunately, we’re nobody, so maybe we should go back and look at NFS. Luckily, we
can view the NFS exports as nobody:
They correctly exported their directorys as root_squash, however no_all_squash could be our way in. Due to the
NFS security model, this means that we can create a local user with the same UID/GID as frank on the jail box,
mount the nfs share, and use it as if we were frank.
Let’s mount the nfs directory, create a user named frank and make sure the UID and GID are correct:
Now we should be able to upload files onto the jail server as if we were frank. The easiest way in
from here would be to upload a key to authorized_keys so that we can SSH in as frank, since we saw port 22 was open
in our nmap scan.
Since we can upload any kind of file as frank, the way forward is to write a file in C with suid as frank, which
writes our public key into /home/frank/.ssh/authorized_keys. Since this is relatively simple, and this is already a long
post, I’ll leave that as an exercise to the reader.
Now we can ssh in as frank and can poke around for priv-esc. Once again, sudo -l shows us the way:
So, we can’t get root, but we can get adm. Remembering back to our enumeration as nobody, there was a /var/adm folder
which adm had access to. Maybe we can take a peek there?
We can’t execute any shell commands in rvim, but we can still use :e to view directories and files. So, if we do :e /var/adm
we can see the contents:
and .local:
Opening note.txt gives us an encrypted message. Due to all of the repetition, it looks like a simple substituion cipher, and it is
(quipqiup suffices):
Opening .frank gives us the next huge hint:
Finally, we can open keys.rar (with :e again) and re-save it anywhere /opt or /tmp for example (:w) so we can access it. We now have a password
protected rar with a password of the form [lastname?][\d\d\d\d][special]. Using the encrypted hint, we can Google around and find a Frank Morris who attempted an Alcatraz escape and was never found. That gives us Morris[\d\d\d\d][!|?|@|$|%|^] which is trivially easy to brute force, especially if you guess the most common four digit number would be a year (1900-2018).
When we unrar the file, we get a single public key. From here it seems obvious we need to break the public key, so we use RsaCtfTool, and the rest is easy.