Cryptographic Failures (OWASP A02)
Cryptographic failures (formerly "Sensitive Data Exposure") encompass weak encryption, poor key management, insufficient transport security, and plaintext storage of sensitive data. This is the #2 risk in the OWASP Top 10 2021 because cryptographic failures directly lead to data breaches.
TLS/SSL Configuration Testing
# Test SSL/TLS configuration:
# Use testssl.sh (comprehensive):
testssl.sh https://target.com
# Or sslyze:
sslyze target.com
# Quick nmap scan:
nmap --script ssl-enum-ciphers -p 443 target.com
# Check for specific weaknesses:
# Test for SSLv2/SSLv3 (should be disabled):
openssl s_client -ssl2 -connect target.com:443 2>&1 | head -5
openssl s_client -ssl3 -connect target.com:443 2>&1 | head -5
# Test for TLS 1.0/1.1 (should be disabled):
openssl s_client -tls1 -connect target.com:443 2>&1 | head -5
openssl s_client -tls1_1 -connect target.com:443 2>&1 | head -5
# Check certificate details:
openssl s_client -connect target.com:443 2>/dev/null | openssl x509 -noout -text
# Check for weak ciphers:
nmap --script ssl-enum-ciphers -p 443 target.com | grep -E 'RC4|DES|NULL|EXPORT|anon'
# Check for HSTS header:
curl -sI https://target.com | grep -i strict-transport# Test SSL/TLS configuration:
# Use testssl.sh (comprehensive):
testssl.sh https://target.com
# Or sslyze:
sslyze target.com
# Quick nmap scan:
nmap --script ssl-enum-ciphers -p 443 target.com
# Check for specific weaknesses:
# Test for SSLv2/SSLv3 (should be disabled):
openssl s_client -ssl2 -connect target.com:443 2>&1 | head -5
openssl s_client -ssl3 -connect target.com:443 2>&1 | head -5
# Test for TLS 1.0/1.1 (should be disabled):
openssl s_client -tls1 -connect target.com:443 2>&1 | head -5
openssl s_client -tls1_1 -connect target.com:443 2>&1 | head -5
# Check certificate details:
openssl s_client -connect target.com:443 2>/dev/null | openssl x509 -noout -text
# Check for weak ciphers:
nmap --script ssl-enum-ciphers -p 443 target.com | grep -E 'RC4|DES|NULL|EXPORT|anon'
# Check for HSTS header:
curl -sI https://target.com | grep -i strict-transportPassword Storage Analysis
If you obtain password hashes (via SQL injection, database leak, backup files), first identify the algorithm, then assess its strength. The hash format prefix reveals the algorithm:
| Hash Prefix / Length | Algorithm | Strength |
|---|---|---|
| $2b$12$... | bcrypt | Strong |
| $6$... | SHA-512 crypt | OK (salted) |
| $5$... | SHA-256 crypt | OK (salted) |
| $1$... | MD5 crypt | Weak |
| 32 hex chars | MD5 | Very weak |
| 40 hex chars | SHA-1 | Weak |
| 64 hex chars | SHA-256 | Weak if unsalted |
Quick indicators of bad password storage:
- The application can email you your existing password → stored in plaintext or reversible encryption
- Admin panel can display decrypted passwords → reversible encryption, not hashing
- Two users with the same password have the same hash → no salt
Hashcat Commands for Cracking Weak Hashes
hashcat -m 0 hashes.txt /usr/share/wordlists/rockyou.txt # MD5
hashcat -m 100 hashes.txt /usr/share/wordlists/rockyou.txt # SHA-1
hashcat -m 3200 hashes.txt /usr/share/wordlists/rockyou.txt # bcrypthashcat -m 0 hashes.txt /usr/share/wordlists/rockyou.txt # MD5
hashcat -m 100 hashes.txt /usr/share/wordlists/rockyou.txt # SHA-1
hashcat -m 3200 hashes.txt /usr/share/wordlists/rockyou.txt # bcryptData in Transit
# Check for mixed content (HTTPS page loading HTTP resources):
curl -s https://target.com | grep -i 'http://' | grep -v 'https://'
# Check if HTTP redirects to HTTPS:
curl -sI http://target.com
# Should return 301/302 to https://
# If it returns 200 over HTTP → sensitive data sent in cleartext
# Check for sensitive data in URLs:
# URLs are logged in server logs, browser history, proxy logs
# BAD: https://target.com/login?token=abc123
# BAD: https://target.com/reset?email=user@example.com
# Check API authentication over HTTP:
curl -sI http://target.com/api/users -H 'Authorization: Bearer TOKEN'
# If API works over HTTP → credentials sent in cleartext
# Check for sensitive cookies without Secure flag:
curl -sI https://target.com/login -X POST -d 'user=test&pass=test' | grep -i set-cookie
# Cookies should have: Secure; HttpOnly; SameSite=Lax# Check for mixed content (HTTPS page loading HTTP resources):
curl -s https://target.com | grep -i 'http://' | grep -v 'https://'
# Check if HTTP redirects to HTTPS:
curl -sI http://target.com
# Should return 301/302 to https://
# If it returns 200 over HTTP → sensitive data sent in cleartext
# Check for sensitive data in URLs:
# URLs are logged in server logs, browser history, proxy logs
# BAD: https://target.com/login?token=abc123
# BAD: https://target.com/reset?email=user@example.com
# Check API authentication over HTTP:
curl -sI http://target.com/api/users -H 'Authorization: Bearer TOKEN'
# If API works over HTTP → credentials sent in cleartext
# Check for sensitive cookies without Secure flag:
curl -sI https://target.com/login -X POST -d 'user=test&pass=test' | grep -i set-cookie
# Cookies should have: Secure; HttpOnly; SameSite=LaxData at Rest
Check whether sensitive data is stored without encryption. PCI DSS requires encryption of stored cardholder data, and applications should never store full card numbers (only last 4 digits).
Where to Check for Unencrypted Sensitive Data
- • Database backups — are they encrypted?
- • Log files — do they contain passwords, tokens, PII?
- • Error messages — do they reveal database data?
- • Browser localStorage / sessionStorage — plaintext tokens or PII?
- • Cookies — are sensitive values encrypted?
# Check for sensitive data in HTML source:
curl -s https://target.com/account | grep -iE 'ssn|credit.card|password|secret'
# Check for autocomplete on sensitive fields:
curl -s https://target.com/login | grep -i autocomplete
# Password fields should have autocomplete="off" or autocomplete="new-password"# Check for sensitive data in HTML source:
curl -s https://target.com/account | grep -iE 'ssn|credit.card|password|secret'
# Check for autocomplete on sensitive fields:
curl -s https://target.com/login | grep -i autocomplete
# Password fields should have autocomplete="off" or autocomplete="new-password"Weak Cryptographic Implementations
ECB mode encryption preserves patterns — if the same input always produces the same output (e.g., in encrypted cookies), the application likely uses ECB mode. Also check for predictable tokens: if password reset tokens are sequential or time-based, they can be guessed.
# Generate multiple password reset tokens and look for patterns:
for i in $(seq 1 10); do
curl -s -X POST https://target.com/forgot-password \
-d 'email=test@example.com' \
-c - | grep token
done
# Padding oracle test:
# If error messages differ between bad padding and bad data,
# a padding oracle attack is possible.
padbuster https://target.com/api ENCRYPTED_COOKIE 8 -encoding 0# Generate multiple password reset tokens and look for patterns:
for i in $(seq 1 10); do
curl -s -X POST https://target.com/forgot-password \
-d 'email=test@example.com' \
-c - | grep token
done
# Padding oracle test:
# If error messages differ between bad padding and bad data,
# a padding oracle attack is possible.
padbuster https://target.com/api ENCRYPTED_COOKIE 8 -encoding 0Information
crypto.randomBytes in Node.js, secrets.token_hex in Python).
If tokens appear to be based on timestamps, PIDs, or sequential counters, report as a predictable token vulnerability.
Testing Checklist
- 1. Test TLS configuration (versions, ciphers, certificate validity)
- 2. Check HTTP→HTTPS redirect and HSTS header
- 3. Verify cookie security flags (Secure, HttpOnly, SameSite)
- 4. Test password storage (hash algorithm, salting, strength)
- 5. Check for sensitive data in URLs, logs, and error messages
- 6. Check for sensitive data in browser storage
- 7. Test token/nonce predictability
- 8. Check for deprecated crypto (MD5, SHA-1, DES, RC4)
- 9. Test for padding oracle vulnerabilities
Evidence Collection
TLS Report: testssl.sh or sslyze output showing weak configuration
Hash Analysis: Identified hash algorithm and demonstrated weakness
Data Exposure: Screenshots of sensitive data in cleartext
CVSS Range: Weak TLS: 5.3–7.5 | Plaintext passwords: 7.5–9.1 | No encryption on PII: 7.5–8.6
Remediation
- TLS 1.2+ only: Disable SSLv2, SSLv3, TLS 1.0, and TLS 1.1. Use strong cipher suites.
- HSTS: Enable Strict-Transport-Security with max-age=31536000 and includeSubDomains.
- bcrypt/Argon2: Hash passwords with bcrypt (cost 12+) or Argon2id. Never use MD5, SHA-1, or unsalted hashes.
- Encrypt PII at rest: Use AES-256-GCM for sensitive data encryption. Manage keys via KMS/HSM.
- CSPRNG: Use cryptographically secure random number generators for all tokens and secrets.
False Positive Identification
- SHA-256 for non-password hashing: SHA-256 is inappropriate for passwords but perfectly fine for integrity checking, HMAC, and file hashing — assess usage context.
- Short RSA keys in test environments: 1024-bit RSA keys in development/test may be intentional for speed — verify the production deployment uses appropriate key sizes.
- CBC mode with proper IV: AES-CBC is not inherently broken — only report if the IV is static/predictable or if a padding oracle is exploitable.