Sitemap

Bypass TryHackMe Lab

8 min readJul 18, 2026

--

Press enter or click to view image in full size

The network security team has implemented an Intrusion Detection System (IDS) using Suricata to protect the company’s CCTV web panel. My objective was to enumerate the target, trigger the required IDS rules, recover the password, and gain access to the CCTV web panel.

Reconnaissance & Enumeration

Before interacting with the target, I started with reconnaissance and enumeration.

  • Reconnaissance is the process of gathering information about a target to understand its technologies, services, and potential attack surface.
  • Enumeration is the next step, where I actively queried the exposed services to gather more detailed information.

Nmap Enumeration

The first thing I did was run an Nmap scan against every TCP port while enabling the default NSE scripts and version detection.

nmap -sCV -p- 10.113.152.91

This scan checked all 65,535 TCP ports, identified which ports were open, detected the running services, and attempted to determine their versions.

root@ip-10-113-106-93:~# nmap -sCV -p- 10.113.152.91 
Starting Nmap 7.94SVN ( https://nmap.org ) at 2026-07-16 15:45 UTC
Nmap scan report for ip-10-113-152-91.eu-central-1.compute.internal (10.113.152.91)
Host is up (0.00051s latency).
Not shown: 65532 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.9 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 56:13:f8:71:67:43:00:84:95:53:ae:80:84:89:1e:e8 (RSA)
| 256 5e:a1:59:3c:af:99:12:e5:f1:ff:dd:da:8c:41:b5:8e (ECDSA)
|_ 256 89:73:42:b9:27:73:dd:23:e1:b7:d5:73:03:61:8e:81 (ED25519)
80/tcp open http Apache httpd 2.4.41
|_http-title: 403 Forbidden
|_http-server-header: Apache/2.4.41 (Ubuntu)
443/tcp open ssl/http Apache httpd 2.4.41
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=cctv.thm/organizationName=cctv.thm/stateOrProvinceName=Tokyo/countryName=AU
| Not valid before: 2023-08-30T10:08:16
|_Not valid after: 2024-08-29T10:08:16
| tls-alpn:
|_ http/1.1
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: 403 Forbidden
Service Info: Host: default; OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 124.43 seconds

What I learned from the scan

  • 22 SSH OpenSSH 8.2p1 (Ubuntu)
  • 80 HTTP Apache 2.4.41 — Returns 403 Forbidden
  • 443 HTTPS Apache 2.4.41 — SSL certificate for cctv.thm

One thing that immediately stood out was that both the HTTP and HTTPS services behaved differently.

  • Accessing HTTP (port 80) always returned 403 Forbidden.
  • The SSL certificate revealed the hostname cctv.thm, which suggested the web server was configured for virtual hosting.

That told me the application expected requests for cctv.thm, not simply the IP address.

Press enter or click to view image in full size
Press enter or click to view image in full size

Adding the Hostname

To make my browser and command-line tools send the correct Host header, I added the hostname to /etc/hosts.

echo "10.113.152.91 cctv.thm" | sudo tee -a /etc/hosts

After doing this, I tested both HTTP and HTTPS.

http://cctv.thm

returned

403 Forbidden

while

https://cctv.thm

loaded successfully after accepting the self-signed certificate.

Press enter or click to view image in full size

I also inspected the HTTP headers.

curl -I https://cctv.thm -k

The response contained a PHPSESSID cookie, which immediately told me the web application was built with PHP.

I also checked for common files such asrobots.txt, but nothing interesting was exposed.

root@ip-10-113-106-93:~# curl -I https://cctv.thm -k
HTTP/1.1 200 OK
Date: Thu, 16 Jul 2026 16:32:19 GMT
Server: Apache/2.4.41 (Ubuntu)
Set-Cookie: PHPSESSID=hdl7mpv550c2h0fvhg82ndnrm3; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Content-Type: text/html; charset=UTF-8
root@ip-10-113-106-93:~# curl -I http://cctv.thm
HTTP/1.1 403 Forbidden
Date: Thu, 16 Jul 2026 16:33:17 GMT
Server: Apache/2.4.41 (Ubuntu)
Content-Type: text/html; charset=iso-8859-1
root@ip-10-113-106-93:~# curl -I https://cctv.thm/robots.txt -k
HTTP/1.1 404 Not Found
Date: Thu, 16 Jul 2026 16:33:56 GMT
Server: Apache/2.4.41 (Ubuntu)
Content-Type: text/html; charset=iso-8859-1

Inspecting the Website

After gaining access to the HTTPS site, I inspected the HTML source looking for comments, hidden endpoints, JavaScript files, or developer mistakes.

Although I did not immediately discover anything useful in the source code, I noted the referenced JavaScript files for later investigation.

Press enter or click to view image in full size

Directory Enumeration

Next, I performed directory brute-forcing using FFUF.

ffuf -u https://cctv.thm/FUZZ \
-w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt \
-k -mc 200,204,301,302,307,401,403

This revealed a new directory:

/mail

I then enumerated that directory as well.

ffuf -u https://cctv.thm/mail/FUZZ \
-w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt \
-k -mc 200,204,301,302,307,401,403

Inside /mail I found a file called dump.txt.

This turned out to be the most important discovery during enumeration because it contained an internal email explaining exactly how password recovery worked.

dump.txt

The email explained that Suricata IDS had been configured to detect five different network events.

Get Gamuchirai’s stories in your inbox

Join Medium for free to get updates from this writer.

Instead of recovering the password directly, I first had to intentionally trigger each IDS rule and then retrieve a flag from:

/fpassword.php?id=<number>

Each flag represented part of the Stage I password.
Below is the email:

From: steve@cctv.thm
To: mark@cctv.thm
Subject: Important Credentials
Hey Mark,I have completed all the formalities for securing our CCTV web panel (cctv.thm:443). I have installed Suricata to automatically detect any invalid connection and enabled two-layer protection for the web panel. I will SMS you the passwords but incase if you misplace them, there is no possibility for recovery. We can recover the password only if we send some specially crafted packets 	
- Make a UDP request to the machine with source port number 5000. Once done, you can fetch the flag through /fpassword.php?id=1
- Make a TCP request to fpassword.php?id=2 with user-agent set as "I am Steve Friend". Once done, you can fetch the flag through /fpassword.php?id=2
- Send a ping packet to the machine appearing as Mozilla browser (Hint: packet content with user agent set as Mozilla). Once done, you can fetch the flag through /fpassword.php?id=3
- Attempt to login to the FTP server with content containing the word "user" in it. Once done, you can fetch the flag from /fpassword.php?id=4
- Send TCP request to flagger.cgi endpoint with a host header containing more than 50 characters. Once done, you can fetch the flag from /fpassword.php?id=5
After receiving all the flags, you can visit the MACHINE IP that will ask you for the password. The first password will be concatenated values of all five flags you have received above.For the second layer of security, I have enabled a wholly sandboxed login environment with no connection to the database and no possibility of command execution. The username is the computer's hostname, and the password is the same as the previous password. I will SMS you the details as well.
See ya soon
Steve
Dev Ops Engineer

Flag 1 — UDP Packet

The first requirement was to send a UDP packet using source port 5000.
I used Nmap because it allows me to specify the source port easily.

nmap -sU -g 5000 -p 1 10.113.152.91
Press enter or click to view image in full size

After triggering the IDS rule, I visited

https://cctv.thm/fpassword.php?id=1

to retrieve the first flag.

Press enter or click to view image in full size

Flag 2 — Custom User-Agent

The second IDS rule required a TCP request using the User-Agent

I am Steve Friend

I used curl for this.

curl -k -A "I am Steve Friend" \
https://cctv.thm/fpassword.php?id=2

Once the IDS detected the request, visiting the same page returned the second flag.

Flag 3 — ICMP Payload

The email mentioned a ping packet “appearing as Mozilla.”

Since ICMP packets do not contain HTTP User-Agent headers, I interpreted this as requiring the payload itself to contain the string Mozilla.

The payload must be supplied in hexadecimal

4d6f7a696c6c61

I sent it using:

ping -p 4d6f7a696c6c61 cctv.thm

Afterwards I retrieved the third flag.

Press enter or click to view image in full size

Flag 4 — FTP Login

The fourth rule required an FTP login attempt containing the word user.

The important part here was not successfully logging into FTP, but simply triggering the IDS signature.

Once the attempt had been detected, I retrieved the fourth flag.

Press enter or click to view image in full size

Flag 5 — Long Host Header

The final IDS rule required sending a request to

/flagger.cgi

using a Host header longer than 50 characters.

For example:

curl -i -s http://cctv.thm/flagger.cgi -H "Host: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"-k
https://cctv.thm/fpassword.php?id=5

The HTTP response itself was irrelevant.

The important part was that Suricata detected the request.

Afterwards I successfully retrieved the fifth flag.
Flag value: THM{12319}

Stage I Password

Once I collected all five flags, I concatenated them in numerical order.

THM{10001}
THM{10125}
THM{13231}
THM{33120}
THM{12319}

Result:

THM{10001}THM{10125}THM{13231}THM{33120}THM{12319}

This became the password for the first authentication stage.

That combined string is the password for the first login layer described in the email. The second layer then uses:

  • Username: the machine’s hostname
  • Password: the concatenated string from the five retrieved values

Stage II — Getting the Username

The email mentioned that the username was the computer’s hostname. I recommend using Burp and also the Developer’s tool.

After submitting the Stage I password, I inspected the page source and noticed something suspicious.

<select name="commands">
<option value="date">Current Date ip-10-113-152-91</option>
</select>

The application allowed selecting commands from a dropdown menu.

This immediately suggested that the value of each <option> was being passed to the server.

Using the browser’s Developer Tools, I duplicated the existing <option> element and changed its value.

For example:

<option value="hostname">Get Hostname</option>

When I selected the new option, the server executed the command and returned the hostname.

I repeated the same process to answer the remaining question.

<option value="lsb_release -r -s">Get Release Number</option>

This returned the Linux release version required by the room.

Press enter or click to view image in full size

Final Flag

After logging into the CCTV web panel using:

  • Username: Machine hostname
  • Password: Concatenated Stage I password

I gained access to the CCTV dashboard and retrieved the final flag.

Press enter or click to view image in full size

Overall, this room was a good demonstration of combining reconnaissance, web enumeration, directory fuzzing, HTTP analysis, and understanding how an IDS such as Suricata can detect specific network traffic. The final stage also highlighted why applications should never trust client-side input, since modifying HTML elements in the browser allowed additional commands to be sent to the server.

--

--

Gamuchirai
Gamuchirai