Image by tryhackme.com
This is a web hacking CTF. The task hinted that it was all about bypassing authentication. The room can be found on TryHackMe.
Enumeration
By default, I checked for running services on the webserver by running a NMAP scan:
sudo nmap -sV -O 10.10.12.57 -p-15000
[sudo] password for kali:
Starting Nmap 7.92 ( https://nmap.org ) at 2022-06-03 22:26 CEST
Nmap scan report for 10.10.12.57
Host is up (0.049s latency).
Not shown: 14998 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.4 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.48 ((Ubuntu))
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.92%E=4%D=6/3%OT=22%CT=1%CU=31433%PV=Y%DS=2%DC=I%G=Y%TM=629A6E7E
OS:%P=x86_64-pc-linux-gnu)SEQ(SP=107%GCD=1%ISR=109%TI=Z%CI=Z%II=I%TS=A)SEQ(
OS:SP=107%GCD=1%ISR=108%TI=Z%CI=Z%TS=A)OPS(O1=M505ST11NW7%O2=M505ST11NW7%O3
OS:=M505NNT11NW7%O4=M505ST11NW7%O5=M505ST11NW7%O6=M505ST11)WIN(W1=F4B3%W2=F
OS:4B3%W3=F4B3%W4=F4B3%W5=F4B3%W6=F4B3)ECN(R=Y%DF=Y%T=40%W=F507%O=M505NNSNW
OS:7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF
OS:=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=
OS:%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=
OS:0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%RI
OS:PCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=S)
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 28.49 seconds
Since only SSH, and a webserver was exposed. I moved on to do a basic directory enumeration.
ffuf -w /usr/share/seclists/Discovery/Web-Content/big.txt -u http://10.10.12.57/FUZZ
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v1.5.0 Kali Exclusive <3
________________________________________________
:: Method : GET
:: URL : http://10.10.12.57/FUZZ
:: Wordlist : FUZZ: /usr/share/seclists/Discovery/Web-Content/big.txt
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200,204,301,302,307,401,403,405,500
________________________________________________
.htaccess [Status: 403, Size: 276, Words: 20, Lines: 10, Duration: 53ms]
.htpasswd [Status: 403, Size: 276, Words: 20, Lines: 10, Duration: 53ms]
assets [Status: 301, Size: 311, Words: 20, Lines: 10, Duration: 49ms]
server-status [Status: 403, Size: 276, Words: 20, Lines: 10, Duration: 52ms]
:: Progress: [20476/20476] :: Job [1/1] :: 812 req/sec :: Duration: [0:00:26] :: Errors: 0 ::
Since I found nothing interesting here, I started to poke around on the website.
Login Page
AJAX? Form?
By trying to sign in to /login.html, and having the dev-tools in Firefox by pressing Ctrl+Shift+I, I could see that pressing the LOGIN button did not trigger any network traffic. This indicated that the authentication probably was handled by JavaScript in the frontend application.
No network traffic registered by failing the authentication
I then inspected the LOGIN button. Here I could see that the "authenticate()" function was called when the button was clicked.
Inspecting the LOGIN button
JS Treasure Hunt
Locating the authenticate function.
By looking at the received JS files, I could see that most of the JavaScripts looked like they came from third-party libraries stored on the webserver, except the main.js file. I inspected it, but did not find the authenticate() function.
I then started to look for embedded JavaScript in the login.html file received from the server. And sure enough, right after the closing main-tag I found it.
<script>
function authenticate() {
a = document.getElementById('uname')
b = document.getElementById('pass')
const RevereString = str => [...str].reverse().join('');
if (a.value=="h3ck3rBoi" & b.value==RevereString("54321@terceSrepuS")) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("flag").innerHTML = this.responseText ;
document.getElementById("todel").innerHTML = "";
document.getElementById("rm").remove() ;
}
};
xhttp.open("GET", "RandomLo0o0o0o0o0o0o0o0o0o0gpath12345_Flag_"+a.value+"_"+b.value+".txt", true);
xhttp.send();
}
else {
alert("Incorrect Password, try again.. you got this hacker !")
}
}
</script>
Reverse engineering
What does the authenticate function do?
By reading the script I could see that the function check to see if the user name, that got to read from the DOM and stored in the variable a, was "h3ck3rBoi", and that the password, stored in the variable b, was the same as "54321@terceSrepuS" reversed.
To quickly check what the string was in reverse, I copied it into my clipboard and reversed it in a terminal.
echo "54321@terceSrepuS" | rev
********************
I used this information to authenticate using the discovered username and password.
This caused the JavaScript to perform an AJAX call to the webserver, and gave me the flag 😀