HIGH header injectionjwt tokens

Header Injection with Jwt Tokens

How Header Injection Manifests in Jwt Tokens

Header injection in JWT tokens occurs when an attacker manipulates the header section of a JSON Web Token to alter its behavior or bypass security controls. The JWT header contains critical metadata about the token's structure and cryptographic operations, making it a prime target for injection attacks.

The most common header injection pattern involves manipulating the alg (algorithm) field. JWT tokens support multiple signing algorithms including HS256 (HMAC with SHA-256), RS256 (RSA with SHA-256), and none (no signature). An attacker can modify the header to change the expected verification algorithm:

Malicious Header: {"alg":"HS256","typ":"JWT"}
Expected Header: {"alg":"RS256","typ":"JWT"}

When a server expects an RS256 token but receives one with HS256, it may incorrectly attempt to verify the signature using the public key as if it were a symmetric key. This works because many JWT libraries don't properly validate that the algorithm in the header matches what was expected.

Another critical injection vector targets the typ (type) field. While typically set to "JWT", an attacker might modify this to reference other token types or introduce unexpected parsing behavior. Some implementations use the typ field to determine processing logic, creating potential for type confusion attacks.

Header injection can also manifest through malformed JSON structures. An attacker might inject additional fields or use JSON parsing quirks to create ambiguous token structures. For example:

{"alg":"HS256","typ":"JWT","x5u":"http://malicious.com/key"}

The x5u (X.509 URL) field, when present in a header, can cause some implementations to fetch external keys, enabling remote key substitution attacks. This becomes particularly dangerous when combined with algorithm confusion.

Critical JWT header injection scenarios include:

  • Algorithm confusion attacks where HS256 tokens are verified as RS256
  • None algorithm exploitation where tokens are accepted without verification
  • Key confusion attacks using x5u or jku (JWK Set URL) fields
  • Custom header field injection to trigger unexpected library behavior
  • JSON parsing ambiguity to create multiple valid interpretations

JWT-Specific Detection

Detecting header injection in JWT tokens requires examining both the token structure and the verification implementation. The first line of defense is validating that the token's header matches expected values before any cryptographic operations.

Static analysis of JWT handling code should verify:

function verifyJwt(token, expectedAlg, publicKey) {
    const [headerB64, payloadB64, signature] = token.split('.');
    
    // Validate algorithm before verification
    const header = JSON.parse(Buffer.from(headerB64, 'base64').toString());
    if (header.alg !== expectedAlg) {
        throw new Error('Algorithm mismatch');
    }
    
    // Reject none algorithm
    if (header.alg === 'none') {
        throw new Error('None algorithm not allowed');
    }
    
    // Verify signature with correct key type
    const isValid = verifySignature(token, publicKey, expectedAlg);
    return isValid;
}

Runtime detection involves monitoring for anomalous token patterns. Tools like middleBrick can scan JWT endpoints to identify header injection vulnerabilities by testing various header manipulations:

  • Algorithm switching (HS256 → RS256, RS256 → HS256)
  • None algorithm injection
  • Malicious x5u and jku field injection
  • Header size and structure anomalies
  • Base64 encoding variations that create parsing ambiguities

Network-level detection should monitor for:

// JWT header anomaly detection
function detectJwtAnomalies(token) {
    const parts = token.split('.');
    if (parts.length !== 3) return 'Invalid structure';
    
    const headerB64 = parts[0];
    let header;
    try {
        header = JSON.parse(Buffer.from(headerB64, 'base64').toString());
    } catch (e) {
        return 'Invalid JSON';
    }
    
    const anomalies = [];
    if (header.alg === 'none') anomalies.push('None algorithm');
    if (header.x5u) anomalies.push('External key reference');
    if (header.jku) anomalies.push('External key set');
    if (header.typ !== 'JWT') anomalies.push('Unexpected type');
    
    return anomalies;
}

Automated scanning with middleBrick tests these injection vectors by submitting modified JWT tokens to endpoints and analyzing responses for authentication bypasses or unexpected behavior. The scanner's 12 security checks include specific JWT header validation to identify vulnerable implementations.

JWT-Specific Remediation

Remediating JWT header injection requires both secure implementation practices and runtime validation. The foundation is using JWT libraries that enforce strict header validation and prevent algorithm confusion.

Secure JWT verification implementation:

// Recommended secure JWT verification
const jwt = require('jsonwebtoken');

function secureVerify(token, publicKey, expectedAlg = 'RS256') {
    // Use key ID if available for key selection
    const options = {
        algorithms: [expectedAlg],
        issuer: 'your-issuer',
        audience: 'your-audience'
    };
    
    try {
        const decoded = jwt.verify(token, publicKey, options);
        return decoded;
    } catch (error) {
        // Log specific error types for monitoring
        if (error.name === 'JsonWebTokenError') {
            console.warn('JWT verification failed:', error.message);
        }
        throw error;
    }
}

// Usage
const publicKey = fs.readFileSync('public.pem');
try {
    const payload = secureVerify(jwtToken, publicKey);
    // Process authenticated request
} catch (error) {
    // Return 401 Unauthorized
}

Key remediation strategies:

  1. Algorithm Whitelisting: Always specify allowed algorithms rather than accepting whatever the token header specifies. Never use "none" algorithm.
  2. Key Type Validation: Ensure the verification key type matches the algorithm. RSA keys for RS256, HMAC keys for HS256.
  3. Header Field Validation: Explicitly reject unexpected header fields like x5u, jku, or custom fields that could trigger external resource fetching.
  4. Timing Attack Prevention: Use constant-time comparison for signature verification to prevent timing attacks.
  5. Token Expiration: Always validate exp (expiration) and nbf (not before) claims.

Additional security controls:

// Comprehensive JWT validation middleware
function jwtMiddleware(req, res, next) {
    const authHeader = req.headers.authorization;
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
        return res.status(401).json({ error: 'Missing token' });
    }
    
    const token = authHeader.substring(7);
    
    try {
        const decoded = secureVerify(token, process.env.PUBLIC_KEY);
        
        // Additional claims validation
        const now = Math.floor(Date.now() / 1000);
        if (decoded.exp < now) {
            throw new Error('Token expired');
        }
        if (decoded.nbf > now) {
            throw new Error('Token not active yet');
        }
        
        // Check for header injection anomalies
        const anomalies = detectJwtAnomalies(token);
        if (anomalies.length > 0) {
            throw new Error('Token header anomalies detected');
        }
        
        req.user = decoded;
        next();
    } catch (error) {
        console.warn('JWT authentication failed:', error.message);
        res.status(401).json({ error: 'Invalid token' });
    }
}

Regular security testing with tools like middleBrick ensures these protections remain effective. The scanner's continuous monitoring can detect when new header injection vectors emerge or when implementation changes inadvertently introduce vulnerabilities.

Frequently Asked Questions

What's the difference between HS256 and RS256 JWT token attacks?
HS256 uses symmetric keys where the same secret signs and verifies tokens, making it vulnerable to key confusion attacks if an RS256 implementation incorrectly treats an HS256 token as RS256 and uses a public key as if it were a symmetric key. RS256 uses asymmetric keys with separate public/private key pairs, preventing this specific confusion but introducing other risks like malicious x5u field exploitation that can fetch attacker-controlled public keys.
How does middleBrick detect JWT header injection vulnerabilities?
middleBrick tests JWT endpoints by submitting modified tokens with various header manipulations including algorithm switching (HS256→RS256), none algorithm injection, and malicious x5u/jku fields. It analyzes responses for authentication bypasses, unexpected behavior, or error messages that reveal vulnerable implementations. The scanner's 12 security checks specifically target JWT header validation weaknesses and map findings to OWASP API Top 10 risks.