Denial Of Service with Jwt Tokens
How Denial of Service Manifests in JWT Tokens
A JWT‑based denial of service (DoS) attack does not rely on network flooding; it abuses the verification logic that services run on every request. When an attacker can supply a token that forces the verifier to perform expensive work — or to reject the token only after consuming significant resources — the service can be slowed or made unavailable for legitimate users.
- Algorithm confusion / "none" attack: If the verification code accepts the
nonealgorithm, the attacker sends a token withalg:noneand a valid signature omitted. Some libraries will still run the signature‑verification routine, which may fall back to a costly public‑key operation or trigger exception handling that consumes CPU and memory. - Excessive claim size: JWTs are base64url‑encoded JSON. By inflating standard claims (e.g.,
sub,aud) or adding custom claims with megabytes of data, the attacker increases the payload size. Each request then requires the server to allocate large strings, decode them, and validate the claims, leading to memory exhaustion. - Missing or far‑future expiration: Tokens without a
expclaim or with an expiration years ahead allow replay attacks. An attacker can reuse the same token thousands of times, bypassing rate‑limiting that relies on short‑lived tokens and forcing the server to repeat verification for each replay. - Costly asymmetric verification: Accepting RS256 tokens with a weak or attacker‑chosen public key (e.g., a key that triggers expensive modular exponentiation) can cause CPU spikes. This pattern was seen in CVE‑2016-10555, where a malformed RSA key caused OpenSSL to hang during verification.
These patterns map to OWASP API4:2023 – Unrestricted Resource Consumption. The attack surface is the authentication check that processes the JWT before any business logic runs.
JWT Tokens‑Specific Detection
Detecting JWT‑related DoS requires looking at both the token’s structure and the verification logic. middleBrick’s black‑box scanner runs twelve parallel checks, and several of them surface the relevant signals:
- Input Validation – flags tokens that exceed a configurable size threshold (default 8 KB) or contain abnormal claim lengths.
- Rate Limiting – detects endpoints that accept the same token repeatedly without enforcing expiration or replay protection.
- Authentication – checks for acceptance of the
nonealgorithm, weak secrets, or missingexp/nbfclaims. - LLM/AI Security – not directly relevant, but the scanner also probes for prompt‑injection style payloads that could be hidden in JWT claims.
Example: scanning a login endpoint that returns a JWT.
# Using the middleBrick CLI (npm package)
npx middlebrick scan https://api.example.com/v1/auth/login
The output includes a finding such as:
{
"category": "Authentication",
"severity": "medium",
"title": "JWT accepts 'none' algorithm",
"description": "The endpoint verified a token with alg:none, allowing an attacker to bypass signature verification and force costly fallback processing.",
"remediation": "Reject any token where header.alg === 'none'. Use a library that enforces an allowed algorithm list."
}
If the scanner observes a token of 12 KB being accepted, it will raise an Input Validation finding with a similar remediation: enforce a maximum JWT size and reject oversized tokens before verification.
These findings give developers concrete, actionable data without needing agents, credentials, or configuration changes.
JWT Tokens‑Specific Remediation
Mitigating JWT‑based DoS focuses on limiting the work the verifier must perform and ensuring tokens are short‑lived and size‑bounded. Apply these fixes in the language‑specific JWT libraries you use.
Node.js (jsonwebtoken)
const jwt = require('jsonwebtoken');
const SECRET = process.env.JWT_SECRET; // strong random string
function verifyToken(token) {
// 1. Reject 'none' algorithm
const decoded = jwt.decode(token, {complete: true});
if (!decoded || decoded.header.alg === 'none') {
throw new Error('Invalid token algorithm');
}
// 2. Enforce size limit (e.g., 8 KB)
if (token.length > 8 * 1024) {
throw new Error('Token too large');
}
// 3. Verify with a strict algorithm list
return jwt.verify(token, SECRET, {algorithms: ['HS256']});
}
// Usage in an Express middleware
app.use((req, res, next) => {
const auth = req.headers.authorization;
if (!auth || !auth.startsWith('Bearer ')) return res.sendStatus(401);
const token = auth.slice(7);
try {
req.user = verifyToken(token);
next();
} catch (err) {
return res.status(401).send({error: 'Invalid token'});
}
});
Python (PyJWT)
import jwt
import os
SECRET = os.getenv('JWT_SECRET')
MAX_TOKEN_LEN = 8 * 1024 # 8 KB
ALGORITHMS = ['HS256']
def verify_token(token: str):
if len(token) > MAX_TOKEN_LEN:
raise jwt.InvalidTokenError('Token exceeds size limit')
# Decode header to check algorithm without verifying signature
header = jwt.get_unverified_header(token)
if header.get('alg') == 'none':
raise jwt.InvalidTokenError('none algorithm not allowed')
# Verify signature and standard claims
return jwt.decode(token, SECRET, algorithms=ALGORITHMS)
# Example Flask before_request
from flask import request, jsonify
@app.before_request
def protect():
auth = request.headers.get('Authorization', '')
if not auth.startswith('Bearer '):
return jsonify({'error': 'Missing token'}), 401
token = auth.split()[1]
try:
request.payload = verify_token(token)
except jwt.PyJWTError as e:
return jsonify({'error': str(e)}), 401
Additional hardening steps:
- Always enforce a short
exp(e.g., 15 minutes) and optionallynbf. - Use a strong, randomly generated symmetric secret (HS256) or a trusted asymmetric key pair; never accept keys from the token itself.
- Log verification failures and consider temporary IP‑based throttling if many malformed tokens are seen from a single source.
- When using third‑party libraries, keep them updated; patches for CVE‑2015-2951 (none algorithm) and CVE‑2016-10555 (RSA key exhaustion) are included in recent releases.
By applying these controls, the service stops accepting tokens that would cause excessive CPU, memory, or repeated verification, thereby neutralizing the JWT‑specific DoS vectors while preserving legitimate authentication flow.
Related CWEs: resourceConsumption
| CWE ID | Name | Severity |
|---|---|---|
| CWE-400 | Uncontrolled Resource Consumption | HIGH |
| CWE-770 | Allocation of Resources Without Limits | MEDIUM |
| CWE-799 | Improper Control of Interaction Frequency | MEDIUM |
| CWE-835 | Infinite Loop | HIGH |
| CWE-1050 | Excessive Platform Resource Consumption | MEDIUM |