CRITICAL integrity failuresjwt tokens

Integrity Failures with Jwt Tokens

How Integrity Failures Manifests in Jwt Tokens

Integrity failures in JWT tokens occur when attackers can modify token claims without detection, allowing them to escalate privileges or bypass authorization checks. The most common manifestation is weak signature algorithms that can be forged.

// Vulnerable: using none algorithm with no signature
const token = jwt.sign({ userId: 1, role: 'user' }, '', { algorithm: 'none' });
// Attacker modifies: { userId: 1, role: 'admin' } and removes signature

Another critical failure occurs when developers don't validate the 'alg' header field. Attackers can change HS256 tokens to HS384 or HS512, forcing the server to use a different key than intended.

// Vulnerable: trusting client-specified algorithm
const token = jwt.sign(payload, secret, { algorithm: 'HS256' });
// Attacker modifies header: "alg": "HS384" and re-signs with HS384

Public key confusion attacks exploit mismatched key types. When a server expects an RSA public key but receives an HMAC key, attackers can forge tokens by signing with the HMAC secret instead of the RSA private key.

// Vulnerable: using public key as HMAC secret
const publicKey = fs.readFileSync('public.pem');
const token = jwt.sign({ userId: 1 }, publicKey, { algorithm: 'HS256' });
// Attacker signs with public key as HMAC secret

Timing attacks on signature verification can also lead to integrity failures. When comparison functions return early on the first mismatch, attackers can brute-force tokens byte-by-byte.

// Vulnerable: insecure string comparison
function insecureCompare(a, b) {
  if (a.length !== b.length) return false;
  for (let i = 0; i < a.length; i++) {
    if (a[i] !== b[i]) return false; // Early return enables timing attacks
  }
  return true;
}

JWT-Specific Detection

Detecting integrity failures in JWT tokens requires examining both the token structure and verification logic. Start by analyzing the token's algorithm field and signature strength.

// Detection: check for weak algorithms
function analyzeJwtIntegrity(token) {
  const [headerB64] = token.split('.');
  const header = JSON.parse(Buffer.from(headerB64, 'base64').toString());
  
  if (header.alg === 'none') {
    return 'Critical: No signature algorithm';
  }
  if (header.alg.startsWith('HS') && !isHmacKeyStrongEnough(header.alg)) {
    return 'High: Weak HMAC key for algorithm';
  }
  return 'Secure';
}

Runtime scanning tools can automatically detect these patterns. When middleBrick scans a JWT endpoint, it examines the token verification code for common integrity failures.

Detection CheckRisk LevelWhat It Finds
Algorithm validationCriticalMissing 'alg' header validation
Signature strengthHighWeak keys for HS256/HS384
Key type confusionCriticalPublic key used as HMAC secret
Timing attack surfaceMediumInsecure string comparisons

middleBrick's black-box scanning can detect integrity failures without source code access by submitting crafted tokens and observing server responses. The scanner tests 'none' algorithm support, algorithm confusion attacks, and signature verification timing.

# Using middleBrick CLI to scan JWT endpoints
middlebrick scan https://api.example.com/auth
# The scanner will test:
# - None algorithm acceptance
# - Algorithm confusion (HS256 vs RS256)
# - Weak signature detection

JWT-Specific Remediation

Fixing integrity failures requires strict algorithm validation and secure key management. Always validate the 'alg' header against an allowlist before processing.

// Secure: validate algorithm before verification
const allowedAlgorithms = ['HS256', 'RS256', 'ES256'];

function verifyToken(token, secretOrKey) {
  const [headerB64] = token.split('.');
  const header = JSON.parse(Buffer.from(headerB64, 'base64').toString());
  
  if (!allowedAlgorithms.includes(header.alg)) {
    throw new Error('Invalid algorithm');
  }
  
  return jwt.verify(token, secretOrKey, { algorithms: [header.alg] });
}

Use constant-time comparison functions to prevent timing attacks. Most JWT libraries provide secure verification, but custom implementations need explicit protection.

// Secure: constant-time comparison
const crypto = require('crypto');

function constantTimeCompare(val1, val2) {
  return crypto.timingSafeEqual(
    Buffer.from(val1), 
    Buffer.from(val2)
  );
}

Separate key types completely to prevent confusion attacks. Never use RSA public keys for HMAC operations.

// Secure: separate key storage
const keys = {
  hmac: process.env.HMAC_SECRET,
  rsa: {
    public: fs.readFileSync('public.pem'),
    private: fs.readFileSync('private.pem')
  }
};

function verifyJwt(token) {
  const decoded = jwt.decode(token, { complete: true });
  const header = decoded.header;
  
  if (header.alg.startsWith('HS')) {
    return jwt.verify(token, keys.hmac, { algorithms: [header.alg] });
  } else if (header.alg.startsWith('RS')) {
    return jwt.verify(token, keys.rsa.public, { algorithms: [header.alg] });
  }
  throw new Error('Unsupported algorithm');
}

Implement key rotation and versioning to limit the impact of compromised keys. Use kid (key ID) headers to specify which key to use for verification.

// Secure: key rotation with kid
const keys = {
  '1': process.env.HMAC_SECRET_V1,
  '2': process.env.HMAC_SECRET_V2
};

function verifyTokenWithKid(token) {
  const decoded = jwt.decode(token, { complete: true });
  const header = decoded.header;
  
  if (!header.kid || !keys[header.kid]) {
    throw new Error('Invalid key ID');
  }
  
  return jwt.verify(token, keys[header.kid], { 
    algorithms: [header.alg] 
  });
}

Frequently Asked Questions

Why is the 'none' algorithm so dangerous in JWT tokens?
The 'none' algorithm creates unsigned tokens that any party can modify without detection. When a server accepts 'none' tokens, attackers can simply remove the signature portion and change any claim values. This completely breaks authentication and authorization since the server cannot verify token integrity. Always reject 'none' algorithm tokens and validate the 'alg' header strictly.
How does middleBrick detect JWT integrity failures without source code?