CWE-1321 in APIs
- CWE ID
- CWE-1321
- Category
- Input Validation
- Severity
- HIGH
- Short Name
- Prototype Pollution
What is CWE-1321?
CWE-1321, titled "Insufficient Entropy in API Keys," describes a weakness where an API generates cryptographic keys, tokens, or other secrets using insufficient randomness or entropy. This results in predictable or easily guessable values that can be exploited by attackers.
The core issue stems from using weak random number generators, predictable seeding mechanisms, or insufficient bit length when generating API keys, JWT tokens, session identifiers, or other security-critical values. When entropy is insufficient, attackers can brute-force, guess, or predict valid credentials, bypassing authentication entirely.
Common manifestations include:
- API keys generated from sequential numbers or timestamps
- Tokens using weak random number generators (like Python's
randominstead ofsecrets) - Session IDs with predictable patterns
- Short key lengths that fall within feasible brute-force ranges
CWE-1321 in API Contexts
In API environments, CWE-1321 manifests through several critical vectors that directly impact authentication and authorization systems.
API Key Generation
Many APIs generate API keys using predictable patterns:
def generate_weak_api_key():
# Predictable timestamp-based key
return f"API-{int(time.time())}-{random.randint(1000,9999)}"This approach creates keys that are trivially guessable, especially when attackers know the approximate generation time.
JWT Token Issues
JSON Web Tokens often suffer from insufficient entropy in their kid (key ID) headers or nonce values:
def create_weak_jwt():
# Using predictable key IDs
header = {
'typ': 'JWT',
'alg': 'HS256',
'kid': 'key-001' # Predictable key identifier
}
# ...Session Management
Session identifiers generated without sufficient entropy become vulnerable to session fixation or brute-force attacks:
def create_weak_session_id():
# Only 4 digits of randomness
return f"sess-{random.randint(1000,9999)}"With just 10,000 possible values, this can be exhausted in milliseconds.
Nonce and Challenge Values
Authentication challenges and nonce values used in multi-factor flows must also maintain sufficient entropy:
def generate_weak_nonce():
# Only 6 numeric characters
return ''.join(random.choices('0123456789', k=6)) # 1 million possibilitiesWhile 1 million seems large, modern hardware can test millions of combinations per second.
Detection
Detecting CWE-1321 requires both static analysis and runtime testing to identify weak entropy sources and test key predictability.
Static Code Analysis
Review code for weak random number generation patterns:
# Vulnerable patterns to flag
import random # Not cryptographically secure
import uuid # May use predictable versions
import time # Timestamp-based generationLook for these anti-patterns:
- Use of
randommodule instead ofsecrets - Timestamp or sequential ID components
- Short key lengths (under 128 bits)
- Predictable prefixes or formats
Runtime Testing
Generate multiple keys and analyze their characteristics:
# Test for predictability
keys = [generate_api_key() for _ in range(100)]
# Check for patterns, sequential values, or limited character setsmiddleBrick API Security Scanning
middleBrick automatically detects CWE-1321 through black-box scanning of your API endpoints. The scanner tests authentication mechanisms by:
- Analyzing API key formats and entropy characteristics
- Testing for predictable token generation patterns
- Identifying weak session management implementations
- Checking nonce and challenge value randomness
The scan takes 5–15 seconds and provides a security risk score with specific findings about insufficient entropy vulnerabilities. middleBrick's continuous monitoring (Pro plan) can alert you when new endpoints exhibit weak entropy patterns.
Entropy Analysis Tools
Statistical analysis can quantify entropy:
import secrets
import math
def calculate_entropy(key):
# Calculate Shannon entropy
char_counts = {}
for char in key:
char_counts[char] = char_counts.get(char, 0) + 1
entropy = 0
for count in char_counts.values():
probability = count / len(key)
entropy -= probability * math.log2(probability)
return entropy
# Good entropy: ~5-6 bits per character for alphanumeric keysRemediation
Fixing CWE-1321 requires implementing cryptographically secure random number generation and ensuring sufficient key length and complexity.
Correct Random Number Generation
Replace weak generators with cryptographically secure alternatives:
# Vulnerable - DO NOT USE
import random
import time
def generate_weak_key():
return f"API-{int(time.time())}-{random.randint(1000,9999)}"Secure Implementation
# Secure - USE THIS INSTEAD
import secrets
import string
def generate_secure_api_key(length=32):
alphabet = string.ascii_letters + string.digits + "-_.~"
return ''.join(secrets.choice(alphabet) for _ in range(length))
def generate_secure_jwt_secret():
return secrets.token_urlsafe(32) # 256-bit secure tokenKey Length Requirements
Ensure sufficient bit length for your security needs:
- API Keys: Minimum 128 bits (24+ alphanumeric characters)
- JWT Secrets: 256 bits or higher for HS256
- Session IDs: 128+ bits with sufficient character diversity
- Nonces: 128+ bits, ideally 256+ for high-security contexts
Implementation Best Practices
import secrets
import hashlib
def generate_high_entropy_session_id():
# Combine secure random with hashing for additional unpredictability
random_bytes = secrets.token_bytes(32) # 256 bits
session_hash = hashlib.sha256(random_bytes).hexdigest()
return f"sess-{session_hash}"
def generate_cryptographic_nonce():
return secrets.token_hex(16) # 128-bit nonceFramework-Specific Solutions
Python/Flask:
from flask import session
from itsdangerous import URLSafeTimedSerializer
# Secure session management
serializer = URLSafeTimedSerializer(
secret_key=secrets.token_urlsafe(32),
salt=secrets.token_hex(16)
)
def create_secure_session(user_id):
session_token = secrets.token_urlsafe(32)
session[user_id] = session_token
return session_tokenNode.js/Express:
const crypto = require('crypto');
function generateSecureApiKey() {
return crypto.randomBytes(32).toString('base64url');
}
function generateSecureJwtSecret() {
return crypto.randomBytes(32).toString('hex');
}Rate Limiting and Monitoring
Even with secure generation, monitor for brute-force attempts:
from collections import defaultdict
import time
failed_attempts = defaultdict(list)
MAX_ATTEMPTS = 5
LOCKOUT_PERIOD = 300 # 5 minutes
def is_rate_limited(api_key):
now = time.time()
attempts = failed_attempts[api_key]
# Remove old attempts
attempts = [t for t in attempts if now - t < LOCKOUT_PERIOD]
failed_attempts[api_key] = attempts
if len(attempts) >= MAX_ATTEMPTS:
return True
return FalsemiddleBrick Integration
After implementing fixes, use middleBrick to verify remediation:
- Run a full API scan to check for remaining CWE-1321 vulnerabilities
- Monitor continuously with Pro plan to detect any new weak entropy patterns
- Use the GitHub Action to automatically scan in CI/CD pipelines
middleBrick's 12 security checks include specific entropy analysis that validates your implementation meets security standards. The scanner provides actionable findings with severity levels and remediation guidance to ensure your API keys maintain sufficient randomness.