JSON Web Token (JWT) Attacks
What are JWT Attacks?
JSON Web Token (JWT) attacks exploit vulnerabilities in the implementation, validation, and handling of JWTs to bypass authentication, escalate privileges, access sensitive data, or impersonate users. These attacks target the three main components of a JWT: the header, payload, and signature.
JWT Structure
A JWT consists of three parts separated by dots:
header.payload.signature
Example JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJhZG1pbiI6dHJ1ZX0.4PCPy1VMq7xEk1nK6n6A9Dv9i9Q7K3Kz33gqzC8yZz4
Key Characteristics of JWT Attacks
- Authentication bypass: Gain unauthorized access
- Privilege escalation: Elevate user privileges
- Data tampering: Modify token payload
- Algorithm manipulation: Exploit weak algorithms
- Information disclosure: Extract sensitive data
- Session hijacking: Steal user sessions
- Server-side impacts: Affect server security
- Multiple attack vectors: Various exploitation methods
Common JWT Attack Vectors
| Attack Vector | Description | Impact |
|---|---|---|
| None Algorithm | Use "none" algorithm to bypass signature verification | Authentication bypass |
| Algorithm Confusion | Change algorithm from RS256 to HS256 | Signature forgery |
| Weak Secret | Exploit weak signing secrets | Token forgery |
| Token Tampering | Modify token payload without signature | Data manipulation |
| KID Manipulation | Exploit key identifier (KID) parameter | Arbitrary file read |
| JWK Header Injection | Inject malicious JWK header | Key confusion |
| Token Leakage | Steal tokens from logs, URLs, storage | Session hijacking |
| Brute Force | Guess weak signing keys | Token forgery |
| Replay Attacks | Reuse valid tokens | Session hijacking |
| Injection | Inject malicious data into tokens | Server-side exploits |
JWT Attack Techniques
1. None Algorithm Attack
Attack Scenario: Bypassing signature verification by using the "none" algorithm.
Vulnerable Code:
// Node.js example with vulnerable JWT verification
const jwt = require('jsonwebtoken');
function verifyToken(token) {
// Vulnerable: doesn't check algorithm
return jwt.verify(token, secret, { algorithms: ['HS256', 'none'] });
}
Exploitation Process:
- Attacker creates token with "none" algorithm
- Attacker modifies payload (e.g., sets
admin: true) - Attacker removes signature
- Application accepts token without signature verification
- Attacker gains elevated privileges
Example Malicious JWT:
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkF0dGFja2VyIiwiYWRtaW4iOnRydWV9.
Prevention:
- Explicit algorithm: Always specify allowed algorithms
- Algorithm validation: Reject "none" algorithm
- Signature requirement: Require valid signatures
- Library updates: Use updated JWT libraries
- Security testing: Test for algorithm vulnerabilities
2. Algorithm Confusion Attack
Attack Scenario: Changing algorithm from RS256 to HS256 to forge signatures.
Vulnerable Code:
// Java example with vulnerable JWT verification
Jwts.parserBuilder()
.setSigningKey(publicKey) // Uses public key for verification
.build()
.parseClaimsJws(token);
Exploitation Process:
- Attacker obtains public key
- Attacker changes algorithm from RS256 to HS256
- Attacker signs token with public key as HMAC secret
- Application verifies token using public key
- Attacker forges valid tokens
Prevention:
- Algorithm whitelisting: Only allow specific algorithms
- Key validation: Validate key type matches algorithm
- Library configuration: Configure libraries securely
- Key separation: Use different keys for different algorithms
- Security reviews: Review JWT implementation
3. Weak Secret Attack
Attack Scenario: Exploiting weak signing secrets to forge tokens.
Vulnerable Code:
# Python example with weak secret
import jwt
secret = "secret" # Weak secret
token = jwt.encode(payload, secret, algorithm="HS256")
Exploitation Process:
- Attacker identifies weak secret (e.g., "secret", "password")
- Attacker brute forces secret using tools like Hashcat
- Attacker creates valid tokens with forged payloads
- Application accepts forged tokens
- Attacker gains unauthorized access
Prevention:
- Strong secrets: Use cryptographically strong secrets
- Key rotation: Regularly rotate signing keys
- Key management: Use proper key management
- Brute force protection: Implement rate limiting
- Secret scanning: Scan for hardcoded secrets
4. Token Tampering Attack
Attack Scenario: Modifying token payload without signature verification.
Vulnerable Code:
// PHP example with vulnerable token parsing
$token = $_COOKIE['token'];
$parts = explode('.', $token);
$payload = json_decode(base64_decode($parts[1]), true);
// No signature verification!
if ($payload['admin']) {
grantAdminAccess();
}
Exploitation Process:
- Attacker intercepts JWT
- Attacker decodes payload
- Attacker modifies payload (e.g., sets
admin: true) - Attacker re-encodes payload
- Attacker sends modified token
- Application processes modified payload
- Attacker gains elevated privileges
Prevention:
- Signature verification: Always verify signatures
- Complete validation: Validate all token parts
- Secure parsing: Use secure parsing methods
- Library usage: Use well-tested JWT libraries
- Security testing: Test for tampering vulnerabilities
5. KID Manipulation Attack
Attack Scenario: Exploiting the Key Identifier (KID) parameter to read arbitrary files.
Vulnerable Code:
# Python example with vulnerable KID handling
import jwt
import os
kid = header['kid'] # User-controlled KID
key_path = f"/keys/{kid}"
key = open(key_path).read() # Arbitrary file read
payload = jwt.decode(token, key, algorithms=['HS256'])
Exploitation Process:
- Attacker sets KID to
../../../../etc/passwd - Application reads
/etc/passwdas key - Attacker crafts token with known file content as key
- Application verifies token using file content
- Attacker gains arbitrary file read
Prevention:
- KID validation: Validate KID format
- Path sanitization: Sanitize KID paths
- Whitelisting: Whitelist allowed KIDs
- Secure defaults: Use secure default keys
- Input validation: Validate all user input
JWT Security Best Practices
1. Secure Token Generation
Implementation Checklist:
- Use strong cryptographic algorithms (HS256, RS256, ES256)
- Use cryptographically strong secrets/keys
- Set appropriate expiration times
- Include issued-at (iat) claim
- Use unique identifiers (jti) for tokens
- Limit token scope and permissions
- Avoid sensitive data in tokens
Example (Secure JWT Generation in Node.js):
const jwt = require('jsonwebtoken');
const crypto = require('crypto');
// Generate strong secret
const secret = crypto.randomBytes(32).toString('hex');
function generateToken(user) {
const payload = {
sub: user.id,
name: user.name,
role: user.role,
iat: Math.floor(Date.now() / 1000),
exp: Math.floor(Date.now() / 1000) + (60 * 60), // 1 hour
jti: crypto.randomBytes(16).toString('hex')
};
return jwt.sign(payload, secret, {
algorithm: 'HS256',
noTimestamp: false
});
}
2. Secure Token Validation
Implementation Checklist:
- Always verify signatures
- Validate all required claims
- Check token expiration
- Verify issuer (iss) claim
- Verify audience (aud) claim
- Validate algorithm
- Check token revocation status
- Implement proper error handling
Example (Secure JWT Validation in Node.js):
const jwt = require('jsonwebtoken');
function verifyToken(token) {
try {
const decoded = jwt.verify(token, secret, {
algorithms: ['HS256'], // Only allow HS256
audience: 'myapp.com', // Validate audience
issuer: 'auth.myapp.com', // Validate issuer
maxAge: '1h', // Validate max age
clockTolerance: 5, // Allow 5 seconds clock skew
complete: false // Only return payload
});
// Additional validation
if (!decoded.sub || !decoded.jti) {
throw new Error('Invalid token claims');
}
return decoded;
} catch (err) {
console.error('JWT verification failed:', err.message);
throw err;
}
}
3. Secure Token Storage
Storage Options Comparison:
| Storage Method | Security | Convenience | Risk | Best For |
|---|---|---|---|---|
| HTTP-only Cookies | High | Medium | Low | Web applications |
| Secure Cookies | High | Medium | Low | Web applications |
| Session Storage | Medium | High | Medium | Single-page apps |
| Local Storage | Low | High | High | Non-sensitive data |
| Memory | High | Low | Low | Short-lived tokens |
| Server-side | Very High | Low | Very Low | High-security apps |
Secure Cookie Example:
Set-Cookie: token=eyJhbGci...; Path=/; Secure; HttpOnly; SameSite=Strict; Max-Age=3600
4. Secure Token Transmission
Implementation Checklist:
- Always use HTTPS
- Implement HSTS
- Use secure cookies
- Set appropriate SameSite attributes
- Avoid URL parameters
- Implement CSRF protection
- Use short expiration times
- Implement token binding
Example (Secure Headers for JWT Protection):
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-src 'none'; object-src 'none'
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
JWT in Modern Architectures
Microservices Architecture
Challenges:
- Token propagation: Passing tokens between services
- Key management: Managing keys across services
- Token validation: Validating tokens at each service
- Performance: JWT validation overhead
- Revocation: Handling token revocation
Best Practices:
- Centralized auth service: Single service for token issuance
- Key rotation: Regular key rotation
- Short-lived tokens: Short expiration times
- Token introspection: Validate tokens with auth service
- Service mesh: Use service mesh for secure communication
Example (Kubernetes JWT Authentication):
# Kubernetes Ingress with JWT authentication
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: jwt-ingress
annotations:
nginx.ingress.kubernetes.io/auth-url: "https://auth-service/validate"
nginx.ingress.kubernetes.io/auth-response-headers: "Authorization"
spec:
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
Serverless Architectures
Challenges:
- Stateless nature: No persistent storage
- Cold starts: JWT validation latency
- Key distribution: Distributing keys to functions
- Token validation: Validating tokens in each function
- Performance: JWT validation overhead
Best Practices:
- API Gateway: Handle authentication at gateway
- Lambda Authorizers: Use custom authorizers
- Short-lived tokens: Minimize token lifetime
- Key caching: Cache public keys
- Environment variables: Secure key storage
Example (AWS Lambda Authorizer):
exports.handler = async (event) => {
const token = event.authorizationToken;
try {
// Validate token
const decoded = jwt.verify(token, publicKey, {
algorithms: ['RS256'],
audience: 'myapp.com',
issuer: 'auth.myapp.com'
});
// Return IAM policy
return {
principalId: decoded.sub,
policyDocument: {
Version: '2012-10-17',
Statement: [{
Action: 'execute-api:Invoke',
Effect: 'Allow',
Resource: event.methodArn
}]
},
context: {
userId: decoded.sub,
role: decoded.role
}
};
} catch (err) {
console.error('JWT validation failed:', err);
throw new Error('Unauthorized');
}
};
Single Page Applications (SPAs)
Challenges:
- Token storage: Secure storage in browser
- XSS protection: Preventing token theft
- CSRF protection: Preventing cross-site request forgery
- Token refresh: Handling token expiration
- Session management: Managing user sessions
Best Practices:
- HTTP-only cookies: Store tokens in HTTP-only cookies
- Short-lived tokens: Use short expiration times
- Refresh tokens: Implement token refresh flow
- CSRF protection: Use anti-CSRF tokens
- Content Security Policy: Implement CSP
Example (Secure SPA Authentication Flow):
// Secure token handling in SPA
class AuthService {
constructor() {
this.refreshTokenPromise = null;
}
async getAccessToken() {
const token = this.getTokenFromCookie();
if (!token) {
throw new Error('No token available');
}
// Check if token is expired or about to expire
const decoded = this.decodeToken(token);
const now = Date.now() / 1000;
if (decoded.exp - now < 300) { // Less than 5 minutes left
return this.refreshToken();
}
return token;
}
async refreshToken() {
// Prevent multiple refresh requests
if (this.refreshTokenPromise) {
return this.refreshTokenPromise;
}
this.refreshTokenPromise = new Promise(async (resolve, reject) => {
try {
const refreshToken = this.getRefreshTokenFromCookie();
if (!refreshToken) {
throw new Error('No refresh token available');
}
const response = await fetch('/api/auth/refresh', {
method: 'POST',
credentials: 'include', // Send cookies
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ refreshToken })
});
if (!response.ok) {
throw new Error('Token refresh failed');
}
const data = await response.json();
this.setTokenCookie(data.accessToken);
resolve(data.accessToken);
} catch (err) {
this.clearTokens();
reject(err);
} finally {
this.refreshTokenPromise = null;
}
});
return this.refreshTokenPromise;
}
// Helper methods
getTokenFromCookie() { /* ... */ }
getRefreshTokenFromCookie() { /* ... */ }
setTokenCookie(token) { /* ... */ }
clearTokens() { /* ... */ }
decodeToken(token) { /* ... */ }
}
JWT Testing and Detection
Manual Testing Techniques
- Token Analysis:
- Decode JWT using tools like jwt.io
- Analyze header and payload
- Check for sensitive data
- Verify algorithm
- Algorithm Testing:
- Test with "none" algorithm
- Test algorithm confusion
- Test weak algorithms
- Test algorithm downgrade
- Signature Testing:
- Test with invalid signatures
- Test with empty signatures
- Test with modified signatures
- Test with different keys
- Payload Testing:
- Test with modified claims
- Test with added claims
- Test with removed claims
- Test with special characters
- Header Testing:
- Test with modified headers
- Test with added headers
- Test with removed headers
- Test with special characters
Automated Testing Tools
- Burp Suite:
- JWT Editor: Modify and analyze JWTs
- Scanner: Detect JWT vulnerabilities
- Repeater: Test JWT manipulation
- Intruder: Fuzz JWT parameters
- OWASP ZAP:
- Active Scan: Detect JWT vulnerabilities
- Fuzzer: Test JWT manipulation
- Forced User Mode: Test JWT attacks
- Scripting: Custom JWT tests
- Custom Scripts:
- JWT analysis: Scripts to analyze tokens
- Vulnerability scanning: Custom JWT scanners
- Exploitation testing: Scripts to test JWT exploits
- Fuzzing: Automated JWT fuzzing
Example (Python Script for JWT Testing):
import jwt
import requests
from datetime import datetime, timedelta
def test_jwt_vulnerabilities(base_url, token):
results = {
'token': token,
'vulnerabilities': [],
'tests': []
}
# Test 1: None algorithm
try:
header = jwt.get_unverified_header(token)
if header.get('alg') == 'none':
results['vulnerabilities'].append('Token uses "none" algorithm')
else:
# Try to modify token with none algorithm
payload = jwt.decode(token, options={'verify_signature': False})
none_token = jwt.encode(payload, '', algorithm='none')
test_url = f"{base_url}/api/protected"
headers = {'Authorization': f'Bearer {none_token}'}
response = requests.get(test_url, headers=headers)
if response.status_code == 200:
results['vulnerabilities'].append('Vulnerable to none algorithm attack')
except Exception as e:
results['tests'].append({'name': 'None algorithm', 'result': 'Error', 'details': str(e)})
# Test 2: Algorithm confusion
try:
header = jwt.get_unverified_header(token)
if header.get('alg') in ['RS256', 'RS384', 'RS512']:
# Try to change to HS256
payload = jwt.decode(token, options={'verify_signature': False})
hs256_token = jwt.encode(payload, 'public_key_as_secret', algorithm='HS256')
test_url = f"{base_url}/api/protected"
headers = {'Authorization': f'Bearer {hs256_token}'}
response = requests.get(test_url, headers=headers)
if response.status_code == 200:
results['vulnerabilities'].append('Vulnerable to algorithm confusion attack')
except Exception as e:
results['tests'].append({'name': 'Algorithm confusion', 'result': 'Error', 'details': str(e)})
# Test 3: Weak secret
try:
# Try common secrets
common_secrets = ['secret', 'password', '123456', 'admin', 'jwtsecret']
payload = jwt.decode(token, options={'verify_signature': False})
for secret in common_secrets:
try:
jwt.decode(token, secret, algorithms=['HS256'])
results['vulnerabilities'].append(f'Vulnerable to weak secret: {secret}')
break
except:
continue
except Exception as e:
results['tests'].append({'name': 'Weak secret', 'result': 'Error', 'details': str(e)})
# Test 4: Token tampering
try:
payload = jwt.decode(token, options={'verify_signature': False})
# Modify payload
original_payload = payload.copy()
if 'admin' in payload:
payload['admin'] = True
else:
payload['admin'] = True
# Try to re-encode with same signature
header = jwt.get_unverified_header(token)
tampered_token = jwt.encode(payload, '', algorithm=header.get('alg', 'none'))
test_url = f"{base_url}/api/protected"
headers = {'Authorization': f'Bearer {tampered_token}'}
response = requests.get(test_url, headers=headers)
if response.status_code == 200:
results['vulnerabilities'].append('Vulnerable to token tampering')
except Exception as e:
results['tests'].append({'name': 'Token tampering', 'result': 'Error', 'details': str(e)})
# Test 5: KID manipulation
try:
header = jwt.get_unverified_header(token)
if 'kid' in header:
# Try path traversal
malicious_kid = '../../../../etc/passwd'
malicious_header = header.copy()
malicious_header['kid'] = malicious_kid
payload = jwt.decode(token, options={'verify_signature': False})
malicious_token = jwt.encode(payload, '', headers=malicious_header)
test_url = f"{base_url}/api/protected"
headers = {'Authorization': f'Bearer {malicious_token}'}
response = requests.get(test_url, headers=headers)
if response.status_code != 401:
results['vulnerabilities'].append('Potential KID manipulation vulnerability')
except Exception as e:
results['tests'].append({'name': 'KID manipulation', 'result': 'Error', 'details': str(e)})
return results
# Example usage
result = test_jwt_vulnerabilities(
base_url="https://example.com",
token="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
)
print("JWT Vulnerability Test Results:")
print(f"Token: {result['token']}")
print("\nVulnerabilities Found:")
for vuln in result['vulnerabilities']:
print(f"- {vuln}")
print("\nTest Details:")
for test in result['tests']:
print(f"- {test['name']}: {test['result']}")
if 'details' in test:
print(f" Details: {test['details']}")
Code Analysis Techniques
- Static Analysis (SAST):
- Pattern matching: Identify unsafe JWT usage
- Data flow analysis: Trace token flow
- Taint analysis: Track untrusted token data
- Library detection: Identify JWT libraries
- Dynamic Analysis (DAST):
- Runtime monitoring: Monitor JWT handling
- Fuzz testing: Test JWT payloads
- Behavioral analysis: Analyze JWT behavior
- Exploitation testing: Test for JWT exploits
- Interactive Analysis (IAST):
- Runtime instrumentation: Monitor JWT processing
- Input tracking: Track token data flow
- Vulnerability detection: Identify JWT vulnerabilities
- Real-time analysis: Analyze during execution
Example (Semgrep Rule for JWT Vulnerabilities):
rules:
- id: jwt-none-algorithm
pattern: |
$JWT.verify($TOKEN, $SECRET, { algorithms: [..., 'none', ...] })
message: "JWT verification allows 'none' algorithm - vulnerable to authentication bypass"
languages: [javascript, typescript, java, python]
severity: ERROR
metadata:
cwe: "CWE-347: Improper Verification of Cryptographic Signature"
owasp: "A02:2021 - Cryptographic Failures"
- id: jwt-hardcoded-secret
pattern: |
$SECRET = "$HARDCODED_SECRET"
...
$JWT.sign($PAYLOAD, $SECRET, ...)
message: "Hardcoded JWT secret - vulnerable to token forgery"
languages: [javascript, typescript, java, python, ruby]
severity: ERROR
metadata:
cwe: "CWE-798: Use of Hard-coded Credentials"
owasp: "A02:2021 - Cryptographic Failures"
- id: jwt-no-signature-verification
pattern: |
$JWT.decode($TOKEN, { verify: false })
...
// No signature verification
message: "JWT decoded without signature verification - vulnerable to token tampering"
languages: [javascript, typescript, python]
severity: ERROR
metadata:
cwe: "CWE-345: Insufficient Verification of Data Authenticity"
owasp: "A02:2021 - Cryptographic Failures"
- id: jwt-weak-algorithm
pattern: |
$JWT.sign($PAYLOAD, $SECRET, { algorithm: 'HS256' })
...
// No key strength validation
message: "JWT signed with potentially weak algorithm - consider stronger algorithms"
languages: [javascript, typescript, java, python]
severity: WARNING
metadata:
cwe: "CWE-327: Use of a Broken or Risky Cryptographic Algorithm"
owasp: "A02:2021 - Cryptographic Failures"
- id: jwt-no-expiration
pattern: |
$PAYLOAD = { ... }
...
// No 'exp' claim in payload
$JWT.sign($PAYLOAD, ...)
message: "JWT created without expiration claim - vulnerable to replay attacks"
languages: [javascript, typescript, java, python, ruby]
severity: WARNING
metadata:
cwe: "CWE-613: Insufficient Session Expiration"
owasp: "A07:2021 - Identification and Authentication Failures"
JWT Attack Case Studies
Case Study 1: Authentication Bypass (2018)
Incident: JWT algorithm confusion leading to authentication bypass.
Attack Details:
- Vulnerability: Algorithm confusion in JWT verification
- Attack method: Changing algorithm from RS256 to HS256
- Impact: Full authentication bypass
- Discovery: Security researcher
- Exploitation: Publicly disclosed vulnerability
Technical Flow:
- Application used RS256 for token signing
- Application used public key for token verification
- Attacker changed algorithm to HS256 in token header
- Attacker signed token with public key as HMAC secret
- Application verified token using public key
- Attacker gained admin access
Lessons Learned:
- Algorithm validation: Always validate algorithm
- Key separation: Use different keys for different algorithms
- Library configuration: Configure JWT libraries securely
- Security testing: Test for algorithm vulnerabilities
- Vulnerability disclosure: Handle disclosures responsibly
Case Study 2: Data Breach (2020)
Incident: JWT token leakage leading to data breach.
Attack Details:
- Vulnerability: Tokens stored in client-side localStorage
- Attack method: XSS attack to steal tokens
- Impact: 500,000 user records exposed
- Discovery: Security monitoring
- Exploitation: Automated bot attack
Technical Flow:
- Application stored JWT in localStorage
- Application vulnerable to XSS
- Attacker injected malicious script via XSS
- Script extracted JWT from localStorage
- Attacker used stolen tokens to access API
- Attacker exfiltrated user data
- Data sold on dark web
Lessons Learned:
- Secure storage: Use HTTP-only cookies for tokens
- XSS protection: Implement Content Security Policy
- Input validation: Validate all user input
- Output encoding: Encode all output
- Security headers: Implement proper security headers
Case Study 3: Privilege Escalation (2021)
Incident: JWT token tampering leading to privilege escalation.
Attack Details:
- Vulnerability: No signature verification
- Attack method: Modifying token payload
- Impact: 10,000 user accounts compromised
- Discovery: Internal security audit
- Exploitation: Manual testing
Technical Flow:
- Application parsed JWT without signature verification
- Attacker intercepted JWT
- Attacker decoded payload
- Attacker modified
roleclaim from "user" to "admin" - Attacker re-encoded token
- Application processed modified token
- Attacker gained admin privileges
- Attacker accessed sensitive data
Lessons Learned:
- Signature verification: Always verify signatures
- Complete validation: Validate all token parts
- Secure parsing: Use secure parsing methods
- Library usage: Use well-tested JWT libraries
- Security testing: Test for tampering vulnerabilities
Case Study 4: Financial Fraud (2022)
Incident: JWT replay attack leading to financial fraud.
Incident: JWT replay attack leading to financial fraud.
Attack Details:
- Vulnerability: Long-lived JWT tokens
- Attack method: Token replay attack
- Impact: $2 million in fraudulent transactions
- Discovery: Fraud detection system
- Exploitation: Automated attack
Technical Flow:
- Application issued long-lived JWT tokens (30 days)
- User's device compromised
- Attacker stole JWT from device
- Attacker used token to access financial API
- Attacker initiated fraudulent transactions
- Fraud detection system triggered
- Investigation revealed token replay
Lessons Learned:
- Short-lived tokens: Use short expiration times
- Token revocation: Implement token revocation
- Device security: Secure tokens on devices
- Rate limiting: Implement API rate limiting
- Anomaly detection: Monitor for suspicious activity
JWT and Compliance
Regulatory Implications
JWT vulnerabilities can lead to severe compliance violations:
- GDPR: General Data Protection Regulation
- Data protection: JWT attacks can expose personal data
- Breach notification: Requires notification of data breaches
- Fines: Up to 4% of global revenue or €20 million
- User rights: Violations of user data protection rights
- PCI DSS: Payment Card Industry Data Security Standard
- Cardholder data protection: JWT attacks can expose payment data
- Requirement 3: Protect stored cardholder data
- Requirement 6: Develop and maintain secure systems
- Requirement 8: Identify and authenticate access
- HIPAA: Health Insurance Portability and Accountability Act
- PHI protection: JWT attacks can expose protected health information
- Security rule: Implement technical safeguards
- Breach notification: Report breaches affecting PHI
- Privacy rule: Protect individual health information
- NIST SP 800-63: Digital Identity Guidelines
- Authentication security: JWT as authentication mechanism
- Token security: Secure token handling
- Session management: Secure session handling
- Risk management: Manage authentication risks
- ISO 27001: Information Security Management
- Information security: Protect information assets
- Access control: Control access to information
- Cryptography: Use appropriate cryptographic controls
- Compliance: Meet legal and regulatory requirements
Compliance Requirements
| Regulation | Requirement | JWT Security Measure |
|---|---|---|
| GDPR | Protect personal data | Secure token storage, encryption, access controls |
| PCI DSS | Protect cardholder data | Tokenization, encryption, secure storage |
| HIPAA | Protect health information | Secure token handling, encryption, access controls |
| NIST SP 800-63 | Secure authentication | Strong algorithms, secure implementation |
| ISO 27001 | Information security | Secure token lifecycle, access controls |
JWT in the OWASP Top 10
OWASP Top 10 2021: JWT vulnerabilities are primarily related to:
- A02:2021 - Cryptographic Failures: Weak algorithms, poor key management
- A07:2021 - Identification and Authentication Failures: Authentication bypass
- A01:2021 - Broken Access Control: Privilege escalation
- A04:2021 - Insecure Design: Poor token design
Key Points:
- Prevalence: Common in modern web applications
- Exploitability: Can be exploited with moderate skill
- Impact: Can lead to authentication bypass, data breaches
- Detectability: Often detectable with proper testing
- Business Impact: Can cause data breaches, regulatory fines, reputational damage
OWASP Recommendations:
- Algorithm validation: Only allow secure algorithms
- Signature verification: Always verify signatures
- Secure storage: Store tokens securely
- Short expiration: Use short token lifetimes
- Secure transmission: Always use HTTPS
- Input validation: Validate all token input
- Error handling: Secure error handling
- Library updates: Keep libraries updated
- Security testing: Regular vulnerability scanning
Advanced JWT Attack Techniques
1. JWT Header Injection
Technique: Injecting malicious headers into JWT.
Attack Scenario:
- Application allows arbitrary headers in JWT
- Attacker adds malicious headers
- Application processes malicious headers
- Attacker gains server-side impact
Process:
- Attacker crafts JWT with malicious header:
{ "alg": "HS256", "typ": "JWT", "jwk": { "kty": "RSA", "kid": "attacker-key", "use": "sig", "n": "malicious_modulus", "e": "AQAB" } } - Application processes JWK header
- Application uses attacker's key for verification
- Attacker forges valid tokens
Prevention:
- Header validation: Validate allowed headers
- JWK restrictions: Restrict JWK header usage
- Whitelisting: Whitelist allowed header parameters
- Input validation: Validate all header content
- Security testing: Test for header injection
2. JWT Timing Attacks
Technique: Exploiting timing differences in JWT validation.
Attack Scenario:
- Application has timing differences in validation
- Attacker measures validation time
- Attacker infers secret key
- Attacker forges tokens
Process:
- Attacker sends multiple JWTs with different signatures
- Attacker measures validation time for each
- Attacker identifies timing patterns
- Attacker infers secret key bits
- Attacker reconstructs secret key
- Attacker forges valid tokens
Prevention:
- Constant-time validation: Implement constant-time validation
- Rate limiting: Limit validation attempts
- Key rotation: Regular key rotation
- Strong keys: Use cryptographically strong keys
- Security testing: Test for timing vulnerabilities
3. JWT Kid Path Traversal
Technique: Exploiting KID parameter for path traversal.
Attack Scenario:
- Application uses KID to load keys
- Application doesn't validate KID
- Attacker provides malicious KID
- Application reads arbitrary files
Process:
- Attacker crafts JWT with malicious KID:
{ "alg": "HS256", "typ": "JWT", "kid": "../../../../etc/passwd" } - Application reads
/etc/passwdas key - Attacker crafts token with file content as key
- Application verifies token using file content
- Attacker gains arbitrary file read
Prevention:
- KID validation: Validate KID format
- Path sanitization: Sanitize KID paths
- Whitelisting: Whitelist allowed KIDs
- Secure defaults: Use secure default keys
- Input validation: Validate all user input
4. JWT Algorithm Downgrade
Technique: Forcing application to use weaker algorithms.
Attack Scenario:
- Application supports multiple algorithms
- Attacker changes algorithm to weaker one
- Application uses weaker algorithm
- Attacker exploits weaker algorithm
Process:
- Application supports RS256 and HS256
- Attacker changes algorithm from RS256 to HS256
- Application verifies token with HS256
- Attacker exploits weaker algorithm
- Attacker forges valid tokens
Prevention:
- Algorithm whitelisting: Only allow secure algorithms
- Algorithm validation: Validate algorithm matches key type
- Key separation: Use different keys for different algorithms
- Security testing: Test for algorithm downgrade
- Library configuration: Configure libraries securely
5. JWT Token Sidejacking
Technique: Stealing JWT tokens from network traffic.
Attack Scenario:
- Application transmits JWT over insecure channels
- Attacker intercepts network traffic
- Attacker steals JWT
- Attacker uses stolen token
Process:
- Application transmits JWT in URL or headers
- Attacker performs MITM attack
- Attacker captures JWT
- Attacker uses JWT to access application
- Attacker hijacks user session
Prevention:
- HTTPS: Always use HTTPS
- HSTS: Implement HTTP Strict Transport Security
- Secure cookies: Use secure, HTTP-only cookies
- Token binding: Bind tokens to specific channels
- Short expiration: Use short token lifetimes
JWT Security Checklist
Development Phase
- Use secure JWT libraries
- Implement algorithm whitelisting
- Use strong cryptographic algorithms
- Use cryptographically strong keys
- Set appropriate token expiration
- Include issued-at (iat) claim
- Use unique identifiers (jti) for tokens
- Limit token scope and permissions
- Avoid sensitive data in tokens
- Implement secure token generation
- Implement secure token validation
- Handle token errors securely
- Implement token revocation
- Secure token storage
- Secure token transmission
Deployment Phase
- Configure HTTPS
- Implement HSTS
- Set secure cookie attributes
- Implement CSRF protection
- Configure security headers
- Set up monitoring
- Implement rate limiting
- Configure logging
- Set up alerting
- Implement backup and recovery
Maintenance Phase
- Regular security testing
- Vulnerability scanning
- Penetration testing
- Key rotation
- Library updates
- Patch management
- Incident response
- Security audits
- Compliance checks
- Continuous monitoring
Conclusion
JSON Web Token (JWT) attacks represent a significant threat to modern web applications, enabling attackers to bypass authentication, escalate privileges, access sensitive data, and compromise systems. As JWTs have become the de facto standard for authentication and authorization in web applications, APIs, and microservices, understanding and mitigating JWT vulnerabilities has become essential for security professionals.
The unique characteristics of JWT vulnerabilities make them particularly dangerous:
- Authentication bypass: Can completely bypass security controls
- Privilege escalation: Can elevate user privileges
- Data tampering: Can modify application state
- Algorithm manipulation: Can exploit weak algorithms
- Information disclosure: Can expose sensitive data
- Session hijacking: Can steal user sessions
- Multiple attack vectors: Various exploitation methods
- Wide impact: Affects many modern applications
Effective JWT attack prevention requires a comprehensive, multi-layered approach that addresses vulnerabilities at every stage of the token lifecycle:
- Secure generation: Use strong algorithms and keys
- Secure validation: Always verify signatures and claims
- Secure storage: Store tokens securely on client and server
- Secure transmission: Always use HTTPS and secure channels
- Secure expiration: Use short token lifetimes
- Secure revocation: Implement token revocation
- Input validation: Validate all token input
- Error handling: Handle errors securely
- Monitoring: Monitor token usage
- Testing: Regular security testing
As web technologies continue to evolve with new authentication methods, complex architectures, and sophisticated security requirements, the threat landscape for JWT attacks will continue to expand. Developers, security professionals, and organizations must stay vigilant, keep learning, and implement comprehensive security measures to protect against these evolving threats.
The key to effective JWT security lies in secure design principles, defense-in-depth strategies, continuous monitoring, and proactive security testing. By understanding the mechanisms, techniques, and prevention methods of JWT attacks, organizations can significantly reduce their risk and protect their systems from this pervasive attack vector.
Remember: JWT vulnerabilities are not just technical issues - they represent serious business risks that can lead to data breaches, regulatory fines, reputational damage, financial losses, and complete system compromise. Taking JWT security seriously and implementing proper security controls at every layer is essential for protecting your organization, your customers, your data, and your reputation.
The cost of prevention is always less than the cost of recovery - invest in JWT security now to avoid catastrophic consequences later. Use secure algorithms, validate all tokens, store tokens securely, transmit tokens safely, and implement comprehensive security measures to protect against JWT attacks.
Security is not a one-time effort but a continuous process - stay informed about emerging threats, keep your systems updated, and maintain a proactive security posture to ensure the integrity, confidentiality, and availability of your applications in today's complex threat landscape.
Your authentication security is your business security - don't let JWT vulnerabilities compromise the trust your users have placed in your applications and services. Secure your tokens, protect your authentication, and maintain the integrity of your digital infrastructure in the face of evolving web security threats.
Insecure Direct Object Reference (IDOR)
Insecure Direct Object Reference (IDOR) is a web security vulnerability that allows attackers to access unauthorized data by manipulating direct object references, bypassing access controls.
JWT (JSON Web Token)
Learn about JSON Web Tokens (JWT), the compact, URL-safe standard for securely transmitting information between parties as JSON objects.
