📋 What Is It?
Cryptographic Failures occur when applications fail to adequately protect sensitive data through proper encryption, hashing, or other cryptographic controls. This often leads to exposure of passwords, credit cards, health records, and personal data.
#2
OWASP Rank
4.49%
Incidence Rate
233K
Occurrences
⚠️ Common Exploits
- Weak Hashing: Using MD5/SHA-1 for password storage
- Missing Encryption: Storing sensitive data in plaintext
- No HTTPS: Transmitting data over unencrypted HTTP
- Hard-coded Keys: Encryption keys embedded in source code
- Weak Randomness: Predictable tokens for sessions/passwords
- ECB Mode: Using insecure encryption modes
🔴 Attack Flow
1. Attacker obtains database dump
↓
2. Finds password hashes using MD5
↓
3. Runs hashes through rainbow table
↓
4. Cracks passwords in seconds
↓
5. BREACH: Access to user accounts!
↓
2. Finds password hashes using MD5
↓
3. Runs hashes through rainbow table
↓
4. Cracks passwords in seconds
↓
5. BREACH: Access to user accounts!
❌ Vulnerable Code
// Bad: Weak password hashing with MD5
import hashlib
def store_password(username, password):
# MD5 is too fast - crackable in seconds!
password_hash = hashlib.md5(password.encode()).hexdigest()
database.save(username, password_hash)
// Bad: Storing sensitive data in plaintext
class User:
def __init__(self, ssn, credit_card):
self.ssn = ssn # Plaintext!
self.credit_card = credit_card # Plaintext!
// Bad: Hard-coded encryption key
SECRET_KEY = "my-secret-key-123" # Exposed in code!
✅ Secure Code
// Good: Strong password hashing with bcrypt
import bcrypt
def store_password(username, password):
# Bcrypt is slow (good!) and includes salt
salt = bcrypt.gensalt(rounds=12)
password_hash = bcrypt.hashpw(password.encode(), salt)
database.save(username, password_hash)
// Good: Encrypt sensitive data
from cryptography.fernet import Fernet
import os
class User:
def __init__(self, ssn, credit_card):
cipher = Fernet(os.environ.get('ENCRYPTION_KEY').encode())
self.ssn_encrypted = cipher.encrypt(ssn.encode())
self.cc_encrypted = cipher.encrypt(credit_card.encode())
// Good: Load keys from environment
SECRET_KEY = os.environ.get('SECRET_KEY')
if not SECRET_KEY:
raise ValueError("SECRET_KEY not set")
✓ Prevention Checklist
- Use bcrypt, Argon2, or scrypt for passwords
- Never use MD5, SHA-1, or plain SHA-256 for passwords
- Encrypt sensitive data at rest (AES-256-GCM)
- Always use HTTPS/TLS for data in transit
- Use TLS 1.2 or higher only
- Store keys in environment variables or key vaults
- Use cryptographically secure random (secrets module)
- Implement HSTS headers
- Never use ECB mode for encryption
- Keep cryptographic libraries updated
🔍 Detection & Tools
Testing Tools:
SSL Labs
testssl.sh
Bandit
Semgrep
Secure Libraries:
bcrypt
cryptography
Argon2
Fernet
How to Test:
- Check hash length (32=MD5, 40=SHA-1, 60=bcrypt)
- Verify HTTPS is enforced
- Test TLS configuration with SSL Labs
- Search code for hard-coded keys
🌍 Real-World Breaches
- LinkedIn (2012): 6.5M passwords hashed with unsalted SHA-1, quickly cracked
- Adobe (2013): 153M accounts with passwords encrypted (not hashed!) with weak ECB mode
- British Airways (2018): £20M GDPR fine for insufficient encryption of payment data
- Equifax (2017): 147M records exposed, including unencrypted SSNs
📌 Quick Tips
- DO NOT use MD5/SHA-1 for passwords
- DO NOT store passwords in plaintext
- DO NOT hard-code encryption keys
- DO use bcrypt/Argon2 for passwords
- DO enforce HTTPS everywhere
- DO encrypt sensitive data at rest
📜 Compliance
Related Standards:
- PCI-DSS Requirement 3.4, 4.1
- GDPR Art. 32 - Security of Processing
- HIPAA Encryption Required
- SOC 2 CC6.1, CC6.7
- NIST 800-53 SC-13