A04:2025 Cryptographic Failures
means sensitive data is protected with missing, weak, or incorrect cryptography. The OWASP A04:2025 page emphasizes that this category can lead to sensitive data exposure or system compromise.
This category is not limited to asking whether encryption is used. It includes deciding which data is sensitive, where it is stored, which channel carries it, which key protects it, how the key is rotated, how passwords are stored, and whether sensitive data remains in secondary surfaces such as logs or caches. Incorrect cryptography often does not break application functionality; the system may appear normal while the data is silently underprotected.
Root Cause
Cryptographic failure usually comes not from not knowing algorithms, but from applying cryptography in the wrong place, for the wrong purpose, or incompletely.
Common mistakes:
- Storing sensitive data in plaintext
- Storing passwords with encryption or fast hashes
- Using weak hashes such as MD5 or SHA1
- Misconfiguring TLS or leaving HTTP fallback
- Putting secret keys in source code
- Reusing the same key across environments or tenants
- Using predictable PRNGs instead of CSPRNGs
- Encrypting without integrity verification
- Leaving sensitive data in caches or logs
Password Storage Mistake
Vulnerable example:
password_hash = hashlib.sha256(password.encode()).hexdigest()
db.save_user(username, password_hash)This approach is fast and weak against offline brute-force attacks. Password storage should use adaptive algorithms with salt and work factor.
Defended approach:
from argon2 import PasswordHasher
ph = PasswordHasher()
password_hash = ph.hash(password)
db.save_user(username, password_hash)Sensitive Data Decision
Not all data requires the same level of protection. Start with data classification:
- Credentials and session tokens
- Passwords and recovery tokens
- Payment or card data
- Health data
- Personal data
- Business secrets
- API keys and signing keys
Without this classification, saying “encrypt everything” is not practical. Decide which data should not be stored, which should be tokenized, which requires at-rest encryption, and which should only exist briefly in memory.
TLS and Transport Security
All sensitive web application traffic should be protected with TLS. However, TLS presence alone is not enough:
- Disable old protocols and weak ciphers
- Apply HSTS
- Validate the certificate chain
- Protect internal service-to-service traffic
- Do not cache sensitive responses
Example secure headers:
Strict-Transport-Security: max-age=31536000; includeSubDomains
Cache-Control: no-store
Pragma: no-cacheTesting Approach
For cryptographic failure testing, ask:
- Where is sensitive data stored and how is it protected?
- Is password hashing adaptive?
- How is key management handled?
- Are secrets present in repositories, images, logs, or crash dumps?
- Is TLS configuration current?
- Is integrity checked alongside encryption?
- Do tokens and reset links have sufficient entropy?
Defensive Controls
- Do not store sensitive data unless necessary.
- Use suitable adaptive hashing such as Argon2, scrypt, bcrypt, or PBKDF2 for passwords.
- Store secrets in a secret manager.
- Apply key rotation and environment separation.
- Define at-rest and in-transit encryption requirements by data class.
- Use authenticated encryption.
- Disable caching for sensitive responses.
Cryptography failures are often silent. The application may appear to work until data is stolen or tokens are guessed.