Back to Cheat Sheets

🔐 Cryptographic Failures

OWASP Web Top 10 - #2

CRITICAL RISK

📋 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!

❌ 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