← Back to all labs
OWASP A04 · LAB ENVIRONMENT

Cryptographic Failures

Cryptographic Failures happen when sensitive data is stored or transmitted with weak, outdated, or missing cryptography — exposing passwords, tokens, and personal data the moment a breach occurs. Try the interactive playground below to see how a weak hash cracks instantly, while a modern one resists it.

OWASP Top 10 · 2025 · A04 — Cryptographic Failures

When “Encrypted” Doesn’t Mean Safe

Cryptographic failures happen when sensitive data — passwords, tokens, credit card numbers — is protected with weak, outdated, or missing cryptography instead of proven, modern methods. A common mistake is confusing hashing (one-way, used for passwords) with encryption (two-way, used for data you need back), then implementing either one badly: fast unsalted hashes like MD5 or SHA1, hand-rolled ciphers, missing TLS, or hardcoded keys. The result is data that looks protected on paper but falls apart the moment an attacker gets a copy of it.

Interactive Demo · Simulated Database Leak

Mode: storing passwords with unsalted MD5
Username Password Hash (leaked) Crack Attempt Result

Code Comparison

Vulnerable
# No salt, fast general-purpose hash
# Crackable at billions of guesses/sec
import hashlib

def store_password(password):
    hash = hashlib.md5(
        password.encode()
    ).hexdigest()
    db.save(hash)
    # same input -> same hash, always
    # rainbow tables crack this instantly
Secure
# Unique salt + deliberately slow hash
# Tunable work factor (rounds)
import bcrypt

def store_password(password):
    salt = bcrypt.gensalt(rounds=12)
    hash = bcrypt.hashpw(
        password.encode(), salt
    )
    db.save(hash)
    # each hash is unique, ~250ms per guess
    # brute force becomes infeasible

Why This Matters

When a database of unsalted MD5 or SHA1 hashes leaks, attackers don’t “hack” anything further — they run the hashes through precomputed rainbow tables or GPU rigs doing tens of billions of guesses per second, and typically recover a large fraction of passwords within minutes. Because so many users reuse passwords across sites, one weakly-hashed database can cascade into account takeovers everywhere else.

How to Detect & Fix

  • Store passwords with a slow, salted algorithm built for the job — bcrypt, scrypt, or Argon2 — with an appropriate work factor, never a general-purpose hash like MD5/SHA1.
  • Never roll your own cryptography or invent a custom obfuscation scheme; use well-reviewed, standard libraries instead.
  • Enforce TLS everywhere (HSTS, no plaintext HTTP fallback) so data in transit can’t be read or tampered with.
  • For data you need to decrypt later, use authenticated encryption such as AES-GCM — never unauthenticated modes like ECB, which leak data patterns.
  • Generate, store, and rotate keys properly using a KMS or HSM — not hardcoded in source, config files, or environment variables committed to a repo.