HIGH denial of servicejwt tokens

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 none algorithm, the attacker sends a token with alg:none and 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 exp claim 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 none algorithm, weak secrets, or missing exp/nbf claims.
  • 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 optionally nbf.
  • 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 IDNameSeverity
CWE-400Uncontrolled Resource Consumption HIGH
CWE-770Allocation of Resources Without Limits MEDIUM
CWE-799Improper Control of Interaction Frequency MEDIUM
CWE-835Infinite Loop HIGH
CWE-1050Excessive Platform Resource Consumption MEDIUM

Frequently Asked Questions

Can middleBrick block a JWT‑based DoS attack in real time?
No. middleBrick is a scanner that detects and reports vulnerabilities such as oversized tokens, acceptance of the ‘none’ algorithm, or missing expiration. It does not block traffic; you must apply the remediation guidance in your API or gateway.
Which OWASP API category covers JWT‑related denial of service?
JWT‑based resource‑exhaustion attacks map to OWASP API4:2023 – Unrestricted Resource Consumption. middleBrick’s Authentication and Input Validation checks specifically look for the patterns that trigger this category.