Arkham — Hackthebox Writeup

Jake Flint
8 min readMar 21, 2021

--

Arkham is a Medium-difficulty box that I picked up in order to get familiar with deserialisation vulnerabilities for the OSWE exam.

Initial nmap output

Nmap shows that IIS 10.0 is running and SMB is open. I check out port 80 and see the default IIS page.

IIS default page on port 80

Gobuster doesn’t find any directories at first, so I assume that there’s a virtual host to find and check out SMB.

SMB share list

Anonymous access appears to be enabled for the “BatShare” share. I find and download a file called “appserver.zip”.

As an anonymous user, I was able to download an archive from the “BatShare” share

Inside the archive I find a note and a LUKS encrypted image file.

The contents of the archive

I don’t find any more information about a virtual host or what the LUKS password could be, so I use a tool called “bruteforce-luks” to try and crack the password.
Hackthebox creators usually don’t make password cracking that bad since it isn’t very fun, so I guess that the password is in rockyou.txt and grep out a wordlist containing the words “batman”, “joker”, “robin” to start with.
I haven’t taken the time to learn how to give my Kali VM access to the GPU so trying to crack LUKS encryption is very slow. Luckily the password is in the first hundred lines of the list.

Using bruteforce-luks to get the LUKS password

I mount the image and decrypt it, and find some images, the script of “Batman Begins”, and a directory called “tomcat-stuff” which contains what I assume to be the web server’s configuration files.

The contents of the decrypted disk image

In “server.xml” I find out about port 8080. I don’t know why my first scan didn’t find it since 8080 is in nmap’s default set of ports, but make a mental note about not being lazy with nmap in the future and move on.

Finding out about port 8080 later

In “web.xml.bak” I find the algorithm that the server uses and the HMAC signing key. I also see that the viewstate is saved on the server. I’ve done a few JWT challenges in CTFs before so I think I know what’s going to happen, but I’m still waiting to encounter the deserialisation issue.

Finding the encryption/signing key in the files obtained through SMB

I check port 8080 next and find the website for a company named “Mask”.

Very HTB-looking page

There isn’t much on the website to interact with except the “Subscription” button which takes me to “http://arkham.htb:8080/userSubscribe.faces”.

The box takes any user input…
And shows this message

I enter “batman@arkham.htb” into the “Sign Up” box and see a confirmation page. I spend a while looking for a reflected XSS vulnerability but am not successful. Viewstates are involved anyway so it’s not like I can send an “admin” an XSS link, either.

I notice that the “Subscribe to us” page contains parameters which my browser sent to the server as POST data.

Examining the POST request

The base64 stands out, so I decode it but find that the base64 decoded data is non-printable. I assume that this means the data is serialised and encrypted with the key we found earlier.

The base64 decoded parameter value seems to be encrypted

I spend some time looking for code/SQL injection vulnerabilities in the other parameters, but I already knew Arkham was about deserialisation so I give up on that.

From the archive I found earlier, I can assume that the Tomcat is the webserver which runs on Java. So I install ysoserial which I’ll use to serialise my payloads.

I spend a couple of hours trying to decrypt the value of the “javax.faces.ViewState” parameter, but am unsuccessful. I do some more reading about HMAC and find that it is as similar to JWT as I suspected. I also find a page that tells me everything I need to know to get RCE on the server.

After the attacker has sent his modified form back to the server the JSF implementation tries to deserialize the provided ViewState. Now even before the deserialization of the ViewState has ended the command is executed and the calculator is started on the server.

I see that ysoserial supports 7 “CommonsCollections” payloads, so I use number 7 to generate a serialised object for the code that I want the server to run.

Generating a pingback payload with ysoserial

I save it in a file and begin writing a Python script which will:

  1. Generate a serialised object for the command I want the webserver to run
  2. Encrypt the payload with the key we found, and generate an HMAC hash
  3. Add the two pieces together and send the POST request to hopefully get RCE
My script to send a signed, serialised payload to the server for RCE

Unfortunately I wasted 2 hours trying to capture stdout for the ysoserial subprocess, and give up and just do that part manually beforehand. The heavy usage of the “print” function shows how much tinkering was required to get it to work.

I always do a simple pingback to confirm RCE first, because I often run into character escaping issues with more complicated payloads and don’t know if I don’t have RCE, or just messed up my command. I set tcpdump to listen for ICMP packets and run my script.

The output of my script (heavy on the debugging)
Receiving ICMP packets from the server

It feels great to see those packets! I set up a netcat listener on port 1337 of course, and then exploit the vulnerability twice more to send nc.exe over and use it to send myself a reverse shell. I call it abc.exe just in case somebody else is working on the same machine.

Receiving a reverse shell from the server through nc.exe

I land on the box as ARKHAM\Alfred and find the user flag.

Obtaining the user flag as “Alfred”

I don’t get any privesc leads from WinPEAS.exe, but in Alfred’s Downloads folder I find a folder containing a zip file. I send that back to my machine and find an Outlook mailbox file inside.

Exfiltrating the zip file I found

There’s a tool called “readpst” that comes with the “libpst4” library. I use it to convert the mailbox to Thunderbird’s format, and have trouble importing it into Thunderbird.

Converting the pst file to a Thunderbird-friendly mbox file

I try letting my OS open it however it wants, and find that mbox files are human readable. In LibreOffice I see an email with a base64 encoded attachment called “image001.png” at the bottom of the file.

Using LibreOffice to find an attached image

Just as the email said, it’s a PNG file.

Base64 decoding the image

The image contains Batman’s password and a share that I can try to access.

The image itself containing Batman’s password

I try to follow the image but am not able to. I’m much more comfortable with a shell than runas shenanigans so I get one with Powershell.

Trying to copy what was happening in the image, but not succeeding

I’m really glad that I decided to send nc.exe over.

Using Batman’s password to run cmd.exe as him and send it back to me
Catching the shell

Batman doesn’t have any interesting folders in his home directory, but he is in the “Administrators” group. I’m not able to access the “Administrator” home folder where I believe the root flag will be though.

Batman is a member of the “Administrators” group

As an Administrator, Batman can probably get SYSTEM privileges by manipulating service paths/binaries, but I try to find the “gotham” share from image001.png earlier.

Trying to copy the image and failing yet again

There’s no such share with that name, but then I remember the other share that Administrators can use. I change to the mounted drive and get the root flag.

Accessing the filesystem through c$ and obtaining the root flag

Privesc was very CTF-like, but the foothold for this box was fantastic and I enjoyed my first experience with a deserialisation vulnerability.
I need to move on to cover more OSWE content, but if I had more time I’d find out why I was unable to deserialise the objects provided by the application.

Putting a blue team hat on, the following problems should be addressed:

  1. Anonymous share access enabled. (I’ve never seen this in a pentest so it mustn’t be a default setting)
  2. Web server configuration accessible via SMB, even if it did require authentication. (I’ve actually encountered this multiple times, except the files were even easier to obtain)
  3. The encryption key needs to be changed now, as it was previously exposed.
  4. The plaintext password in an image was pretty dumb, but I’ve probably seen credentials laying around on more pentests than not.
  5. I have no idea how the ACLs work where that was possible. Maybe accessing c$ gives you SYSTEM privilege or similar?

From a normal shell:

PS C:\Users> icacls Administrator\
icacls : Administrator\: The handle is invalid.
At line:1 char:1
+ icacls Administrator\
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (Administrator\: The handle is invalid.:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError

Successfully processed 0 files; Failed processing 1 files

From the mounted drive through c$:

S:\Users>icacls Administrator
icacls Administrator
Administrator NT AUTHORITY\SYSTEM:(OI)(CI)(F)
BUILTIN\Administrators:(OI)(CI)(F)
ARKHAM\Administrator:(OI)(CI)(F)

--

--

Responses (1)