Lab 75 — StayNest — Stored XSS in Hotel Booking Form
Lab 75 — StayNest — Stored XSS in Hotel Booking Form
Platform: CUSTOM | Category: Web | Type: Challenge | Difficulty: Medium | OS: N/A | **Author: XESXOR Techniques: admin_panel_exploitation, httponly_cookie_bypass, internal_api_exfiltration, stored_xss_injection
Summary
Walkthrough of the CUSTOM Web Lab 75 — StayNest — Stored XSS in Hotel Booking Form. Task: hotel booking platform where admin reviews bookings, HttpOnly cookie blocks external exfiltration. Solution: stored XSS in special_requests field exploits unescaped EJS in admin panel, uses inte
Description
StayNest is a hotel booking platform where travelers can search for hotels, view details, and make reservations. Users create accounts, browse available properties across destinations worldwide, and submit booking requests with their personal details and special requests.
An admin team reviews incoming bookings through an internal management panel. Your goal is to find a way to compromise the admin's session and retrieve the flag.
Credentials provided: user@test.com / password123
English summary: A hotel booking platform where users submit reservations that are reviewed by an admin bot. The goal is to exploit the admin review process to retrieve a flag.
Analysis
-
Initial reconnaissance:
- Logged in with provided credentials
- Found booking form at
/hotel/{id}/bookwith fields: guest_name, phone, address, check_in, check_out, guests, special_requests - Bookings show "Pending Review" status — admin bot reviews them periodically
- Cookie is HttpOnly (
connect.sid) — cannot steal via external exfiltration (webhook.site) /robots.txtreveals/admin/and/api/endpoints- Admin panel at
/admin/bookingsreturns 403 for regular users
-
Identifying the vulnerability:
- The admin panel uses EJS templating with unescaped output tags (
<%- %>) for guest_name, phone, address, and special_requests fields - User input in
special_requestsis HTML-escaped on user's/my-bookingspage but NOT on admin panel - Discovered unauthenticated API endpoint at
/api/bookings/notesthat accepts POST requests to add notes to bookings
- The admin panel uses EJS templating with unescaped output tags (
-
Key vulnerability: Stored XSS in the special_requests field. The admin panel renders this field without escaping, allowing JavaScript execution when admin bot reviews bookings. Combined with an unauthenticated internal API, this enables exfiltration despite HttpOnly cookies.
Solution
Since HttpOnly cookie prevents external exfiltration (webhook.site won't receive cookies), the attack uses the internal notes API to store stolen data:
Step 1: Submit booking with XSS payload
html read-only • copy allowed<img src=x onerror="fetch('/api/bookings/notes',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({booking_id:20,note:document.cookie})})">
This payload:
- Uses
<img src=x onerror=...>to trigger JavaScript (more reliable than<script>tags which may be filtered) - Calls the internal
/api/bookings/notesAPI - POSTs
document.cookieas a note to the booking
Step 2: Wait for admin bot
The admin bot reviews bookings on the admin panel approximately every 20 seconds. When it loads the page, the XSS executes in the admin's browser context.
Step 3: Retrieve the flag
Check /my-bookings — the flag appears in the booking notes section, exfiltrated from the admin's session.
What didn't work
- External webhook exfiltration: Cookie is HttpOnly, so
document.cookiesent to external domains is empty - XSS in profile name field: HTML tags are stripped server-side
- Script tags: May be filtered;
<img onerror>is more reliable
Key Takeaways / Lessons
- Mastering admin_panel_exploitation, httponly_cookie_bypass, internal_api_exfiltration, stored_xss_injection was key to this challenge.
- Always check for common misconfigurations and verify assumptions.
Crafted by XESXOR Research • 2026-04-27 • CUSTOM • Lab 75 — StayNest — Stored XSS in Hotel Booking Form • Difficulty: Medium