HTB ForwardSlash Write-Up
This box was really important for me since it was my first active red box (congratulations to me). I learned a lot things and most above all perseverance. By doing it I fully grasped the philosophy behind Try harder! It is also a fun box where I learned a lot of things and I think that this knowledge will help me during further CTFs.
Foothold
The usual nmap enumeration produces following results
1 | PORT STATE SERVICE VERSION |
In the browser, heading to http://10.10.10.183
redirects to http://forwardslash.htb
. So, forwardslash.htb
must be a hostname in the /etc/hosts/
file. Once done, we get a defaced website hacked by people called Backslash Gang.
The first thing I noticed before checking the page source is they say they hacked the box using vulnerabilities about XML and Automatic FTP Login. I went back to make a second nmap scan to check if I didn’t miss the FTP port the first time but nothing changed. So I supposed that either the FTP service was internal or it has been taken down since they got hacked. Let’s just keep in mind that there was XML and automatic FTP login.
Next come website enumeration using gobuster since there is nothing interesting in the page source. The usual command came back empty.
At this point, I only had one idea in my mind, that is to continue enumeration but with some other known extensions commonly found in a web server plus XML since it is mentionned in the home page.
1 | gobuster dir -t20 -w /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt -u http://forwardslash.htb -x txt,conf,xml -o httpbust.log |
This time, we got a single result named note.txt
which has the following content.
Pain, we were hacked by some skids that call themselves the “Backslash Gang”… I know… That name…
Anyway I am just leaving this note here to say that we still have that backup site so we should be fine.-chiv
From this, I deduced one thing and made a hypothesis:
- Deduction: There is a backup site
- Hypothesis: Pain and chiv are users in the box.
It became pretty clear that the next step is to find the backup site. To do so, it’s obvious we must continue enumeration but enumeration is better when we know where to look and what to look for. A month ago, as script kiddie, I would surely launch gobuster looking for file with extensions like zip
, tar
or gz
since we are talking about backups but let’s not do that and think.
- Their is a backup site which should be browsable or else it would note make sense for chiv to say ‘we should be fine’!
- Gobuster the first time didn’t reveal any subdirectory so no need to try that again!
- When we tried to browse the website using the IP address we were redirected to forwardslash.htb
The last point made it clear since this is a behavior we commonly encounter in apache vhosts. Yes! Vhosts. They are browsable which respects the first point and can sometimes not be a subdirectory which respects the second one. To test my theory, I used gobuster along with SecLists subdomains wordlist to check for vhosts.
1 | gobuster vhost -t20 -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt -u http://forwardslash.htb -o vhostbust.log |
The result came positive with
1 | Found: backup.forwardslash.htb (Status: 302) [Size: 33] |
Browsing to backup.forwardslash.htb
after adding it in /etc/hosts
file welcomes us with a login form.
You know the drill by now:
- Check the page source for interesting stuff.
- Try some default credentials.
- Launch Gobuster.
- Run SQLMap in the login and register forms.
While Gobuster and SQLMap were running, I tried to register as ‘admin
‘, logged in with it and accessed a welcome page.
I did a little exploration using the provided buttons while waiting for SQLMap and Gobuster.
SQLMap came negative for both forms and Gobuster provided the following output:
1 | /index.php (Status: 302) |
Many of these php files are linked to the buttons in the welcome page except api.php
and the dev
folder. The api page gave back as a white page and the dev folder responded with a form for testing their API. Inside the textarea we can see XML!
Oh my God, so there is the XML they were talking about.
I intended to try SQLMap in some of the forms I found during exploration but I immediately dropped the idea when I saw the XML because I’m convinced there is something here following Backslash Gang hint (yes, this is the way).
Executing a query in the form only echoes back the value inside the request tag. Even when we put commands like whoami
, it simply echoes it back instead of executing it. Now talking about XML input on the web, I mainly think about XML eXternal Entity (XXE) vulnerability.
Our favorite PayloadsAllTheThings repo listed many techniques for testing and exploiting this vulnerability. To test if it is vunerable, I followed instructions found in there:
1 |
|
And it echoes Vulnerable. Vulnerability confirmed!
Proceeding to LFI using base64, still following instructions in the repo
1 |
|
gave as output the /dev/index.php
source code encoded in base64.
Decoded, it looks like
1 |
|
Reading this code, I noticed that I got lucky by registering as admin
since it would not work if not. Going down, we notice FTP login credentials: chiv:N0bodyL1kesBack/
. So this is the automatic FTP login they were talking about han!
Next checked if I could login to FTP by giving ftp://127.0.0.1/"
as input inside the request tag and it said that it cannot connect. That answered the question whether the FTP service was internal or was down. But anyway, WE GOT CREDS, and trying them in SSH let us in the box. WAY TO GO!!!
Lateral Movement
In the SSH session, we see that the flag is not owned by our current user chiv
but by pain
. To make lateral movement, I tried my luck by checking if I could make it directly to root from here.
- The command
sudo -l
says I can’t sudo. - No root suid file I can exploit.
So I resigned myself to do the lateral movement.
Listing Pain home dir gives
1 | drwxr-xr-x 7 pain pain 4096 Mar 17 20:28 . |
No bash_history, so we forget about it but there is a note and an interesting folder called encryptorinator
we can read. The note says:
Pain, even though they got into our server, I made sure to encrypt any important files and then did some crypto magic on the key… I gave you the key in person the other day, so unless these hackers are some crypto experts we should be good to go.
-chiv
At this point we have two possibilities. Either the decryption key means something important or the content of the file is important or both. But I’m leaning toward the content of the file since Chiv explicitely said it’s important. Let’s analyze the encryption function in encrypter.py
from encryptorinator directory.
1 | def encrypt(key, msg): |
In my understanding, the function applies each character of the key as a mask sequentially for each character of the message. Now, how to reverse or bruteforce it… ?
One day later, after a lot of paper and ink spent (don’t worry I respected the environment), I tried to reverse it with no luck at all. So I wondered how would it be if the key was made with a single character ?! Out of curiosity, I gave it a shot using a technique I will grossly call known partial plaintext attack (in regards to known-plaintext attack). In my case, I will suppose that ‘the‘, which is frequently used in english, is in the decoded message. The bruteforce.py
file (python2) have the following content:
1 | import sys |
Holy mother of ciphers, I got something seconds later!
Decoded: $7Cq84l’you liked my new encryption tool, pretty secure huh, anyway here is the key to the encrypted image from /var/backups/recovery: cB!6%sdH8Lj^@Y*$C2cf
But I did not get too excited. I have indeed a password but it is for a supposed encrypted image inside /var/backups/recovery
which I can’t list because I don’t have the permission. So this step is maybe for privilege escalation to root once I become Pain! I noted the password somewhere, tried it anyway as pain password but it fails.
I went back to the drawing board and adopted the same methodology I use for privesc in linux boxes. First sudo -l
which I already did without luck and second I look for root suid bins. I tweaked the find command a little to not only find executable suid files but all files owned by pain.
1 | $ find / -user pain -exec ls -l {} + 2>/dev/null |
We have a suid bin /usr/bin/backup
and a backup of a config.php at /var/backups/config.php.bak
. It’s straightforward from here that the backup bin is my way to pain. Running it gives the following output:
1 | ---------------------------------------------------------------------- |
At first glance, it reads a backup file taken at the same second and named specifically. To have more insight at the binary, I downloaded it and ran it with ltrace
.
1 | $ ltrace -s 256 ./backup |
So, I think it does a MD5 hash after getting the current time in format hh:mm:ss. Let’s verify that by making sure that the MD5 hash of 13:34:45
is 7353c957d2897fe84fe5175e58a8d49b
.
1 | $ echo -n "13:34:45" | md5sum |
Yesssss, that’s it! So what I need to do is somehow to “rename” /var/backups/config.php.bak
into a MD5 hash of the time I’m running the command. I put rename in quotes because I don’t have access to the file so the only thing that comes to my mind is a symlink.
Note that instead of aiming for the backup file, I could do it with the user flag but like I’m not racing for first blood, let’s just do it the proper way.
To summarize:
- Get the time in hh:mm:ss.
- Hash it in MD5 and remove the trailing “-“ in the result
- Create a symlink to /var/backups/config.php.bak named as the resulting hash
- Run the backup script.
I poorly came with this command (execute it somewhere you have write permission):
1 | $ v=$(date +%T) && name=$(echo -n "$v" | md5sum | cut -d' ' -f1) && ln -s /var/backups/config.php.bak $name && /usr/bin/backup |
WE GOT CREDS!
However, it does not work in MySQL and like it is written as a “cleartext” password, I considered it as a cleartext password and boom! That’s Pain’s password!
Root Flag
Now we are Pain and have he’s password, sudo -l
shows
1 | Matching Defaults entries for pain on forwardslash: |
It became obvious how to get to root since cryptsetup deals with encrypted volumes, thus the followed mount commands. And if you remember well, we decoded a text talking about an encrypted volume. So let’s bring it back and execute our commands
1 | pain@forwardslash:~$ ls -la /var/backups/recovery/ |
And that’s the ssh key to root without passphrase. Congratulations, you just rooted the box.