Cryptographic key management failures occur when applications mishandle encryption keys, fail to properly authenticate communications, reuse cryptographic values, or implement encryption incorrectly. This includes:
Even perfect algorithms fail when keys are mismanaged or implementation is flawed.
Real-World Attack Scenarios
Scenario 1: Hardcoded Cryptographic Key (CWE-321)
An application has a hardcoded encryption key in source code:
# In source code, version control, and deploymentsSECRET_KEY="MySecretKey2024!@#$%"defencrypt_password(password): cipher =AES.new(SECRET_KEY,AES.MODE_CBC)return cipher.encrypt(password)
The vulnerability:
Hardcoded keys are discoverable:
Visible in source code
Exposed in git history
Visible in compiled binaries
Visible in decompiled applications
Same key used for all deployments
The attack:
Attacker:
Clones git repository
Searches for strings: key =, secret =, password =
Finds: SECRET_KEY = "MySecretKey2024!@#$%"
Uses this key to decrypt all encrypted data
All user passwords, API keys exposed
Result:
Complete encryption bypass
All encrypted data decrypted
Single source for compromising entire application
The fix: Never hardcode keys:
Finding it: Search source code for key =, secret =, password =. Check git history. Decompile if compiled code. Search environment files.
Exploit:
Scenario 2: Unprotected Transport of Credentials (CWE-523)
Application sends API credentials and passwords over HTTP:
The vulnerability:
Credentials sent unencrypted:
Network sniffer captures credentials
Attacker gains authentication
No data protection in transit
All user passwords exposed
The attack:
Attacker on same network (coffee shop WiFi, ISP, corporate network):
Result:
Credential theft
Authentication bypass
Account takeover
Data access
The fix: Always use HTTPS:
And don't send passwords in requests body - use tokens:
Finding it: Check for HTTP endpoints. Monitor network traffic. Intercept requests with Burp Suite. Look for credentials in plaintext transmission.
Scenario 3: Reusing Nonce/IV (CWE-323)
Stream cipher uses same nonce for multiple messages:
The vulnerability:
Nonce reuse with stream cipher:
Keystream is deterministic
XORing two ciphertexts reveals plaintext relationship
Attacker can recover both plaintexts
The attack:
Attacker intercepts two encrypted messages with same nonce:
Result:
Plaintext disclosure
Message recovery without key
The fix: Use random nonce each time:
Finding it: Look for reused nonces/IVs. Check if nonce regenerated for each encryption. Analyze traffic for patterns indicating nonce reuse.
Scenario 4: Key Exchange Without Entity Authentication (CWE-322)
Two systems exchange keys without verifying identity:
The vulnerability:
No authentication during key exchange:
Attacker intercepts key exchange
Sends their own public key instead
Becomes man-in-the-middle
Can decrypt all communications
The attack:
Now:
A encrypts to attacker's key, attacker decrypts, re-encrypts to B
B encrypts to attacker's key, attacker decrypts, re-encrypts to A
Attacker reads all communications
Result:
Man-in-the-middle attack
Complete encryption bypass
All communications compromised
The fix: Authenticate public keys:
Finding it: Check for certificate verification. Test if MITM proxy succeeds. Look for missing signature verification.
Scenario 5: Using Expired Keys (CWE-324)
Application continues using encryption key after expiration:
The vulnerability:
Using keys past expiration:
Keys should be rotated periodically
Expired keys compromise forward secrecy
Extended exposure window increases breach risk
Violates security policy
The attack:
Attacker:
Compromises old encryption key
Even though it's expired, application still uses it
Can decrypt all data encrypted with that key indefinitely
Key rotation never happened
Result:
Extended vulnerability window
Increased risk of compromise
All data encrypted with old key vulnerable
The fix: Enforce key expiration:
Better: Automatic key rotation:
Finding it: Check key expiration logic. Look for keys without expiration dates. Verify key rotation is enforced.
import os
from dotenv import load_dotenv
load_dotenv()
SECRET_KEY = os.getenv('SECRET_KEY')
# Or use Key Management System
from aws_secretsmanager import client
secret = client.get_secret_value(SecretId='encryption-key')
# Search git history
git log -p | grep -i "key\|secret\|password"
# Or search current code
grep -r "SECRET_KEY\|API_KEY\|DB_PASSWORD" .
# Found! Use key to decrypt all data
# Server allows both:
# - TLS 1.3 with AES-256-GCM (secure)
# - SSL 3.0 with DES (broken)
# Client requests TLS 1.3
# Attacker intercepts negotiation
# Forces downgrade to SSL 3.0
# Connection uses DES encryption
Client: "I support TLS 1.3, TLS 1.2, SSL 3.0"
Attacker intercepts, modifies:
Modified: "I support SSL 3.0"
Server: "OK, using SSL 3.0"
Now using 56-bit DES instead of 256-bit AES!