Cryptographic Failures Testing: How to Find OWASP A02 Vulnerabilities
OWASP renamed this category in 2021. It used to be called "Sensitive Data Exposure" — a name that described the symptom rather than the cause. The new name, Cryptographic Failures, is more precise: data gets exposed because the cryptography protecting it was absent, broken, or misconfigured.
That reframing matters for testing. You're not just looking for places where sensitive data leaks. You're looking for places where the cryptographic controls that should prevent that leak are weak, missing, or bypassed. Those are different questions, and they require different techniques.
This guide covers how to test for cryptographic failures systematically — from TLS configuration to password storage to application-layer encryption choices — and what automated tools can and cannot surface.
What Cryptographic Failures Actually Covers
A02 is broad. The common thread is that sensitive data — credentials, tokens, PII, financial records, health data — is either transmitted or stored without adequate cryptographic protection. The failures cluster into four distinct patterns:
Transport layer failures — using outdated TLS versions (1.0, 1.1), weak cipher suites, self-signed certificates, or no HTTPS at all. The data is in transit and readable to anyone on the network path.
Cryptographic algorithm failures — using MD5 or SHA1 for password hashing, AES in ECB mode, static IVs, hardcoded keys, or rolling custom crypto. The data is "encrypted" but recoverable.
Key management failures — keys embedded in source code, stored in plaintext configuration files, never rotated, or shared across environments. The algorithm is fine; the key material is not.
Data classification failures — sensitive data that isn't identified as sensitive, so it ends up in logs, URLs, error messages, or cookies without the protection it needs. No one made a deliberate decision to encrypt it because no one flagged it as requiring encryption.
Common Vulnerability Patterns
Secure and HttpOnly flags. Sensitive data in error messages returned to the client. These aren't algorithm failures — they're data classification failures that lead to exposure.
Testing TLS Configuration
testssl.sh is the right tool for systematic TLS testing. It checks protocol support, cipher suites, certificate validity, and a wide range of known vulnerabilities (BEAST, POODLE, DROWN, Heartbleed, ROBOT) in a single run.
# Full scan — checks protocols, ciphers, and known CVEs
testssl.sh https://target.example.com
# Check only protocols and ciphers (faster)
testssl.sh --protocols --cipher-per-proto https://target.example.com
# Output to JSON for pipeline integration
testssl.sh --jsonfile results.json https://target.example.com
# Check a non-standard port
testssl.sh https://target.example.com:8443
Key findings to look for in the output:
- TLS 1.0 / TLS 1.1 offered — these should be disabled. Modern browsers have removed support; there is no legitimate reason to keep them enabled.
- NULL, EXPORT, or RC4 cipher suites — NULL ciphers provide no encryption at all. EXPORT-grade ciphers are deliberately weak (40-bit keys). RC4 has known biases that allow plaintext recovery.
- Weak DHE parameters — Diffie-Hellman groups smaller than 2048 bits are vulnerable to Logjam. Look for
WEAKorDH 768/DH 1024in the output. - Missing HSTS header — testssl.sh checks for
Strict-Transport-Security. Without it, HTTP-to-HTTPS upgrades can be stripped by an attacker.
For quick spot-checks, nmap's ssl-enum-ciphers script enumerates supported cipher suites by protocol version:
# Enumerate supported ciphers, grouped by TLS version
nmap --script ssl-enum-ciphers -p 443 target.example.com
# Check multiple ports
nmap --script ssl-enum-ciphers -p 443,8443,8080 target.example.com
The SSL Labs API provides a comprehensive graded assessment. Anything below an A rating warrants investigation — a B usually means TLS 1.0/1.1 is still enabled, a C or below indicates serious configuration problems.
Testing for Cleartext Credentials and Missing HSTS
The most straightforward check: visit the login page over HTTP (http:// instead of https://). Three outcomes to distinguish:
- Immediate redirect to HTTPS — good, but check the response headers of the redirect for
Strict-Transport-Security - Login form served over HTTP — critical finding. Credentials submitted on this form are transmitted in cleartext.
- Page loads over HTTP with mixed content — the form action may submit to HTTPS, but other resources loaded insecurely reduce the effective security
To confirm HSTS is properly configured:
# Check HSTS header presence and max-age
curl -sI https://target.example.com | grep -i strict-transport
# Expected output:
# strict-transport-security: max-age=31536000; includeSubDomains; preload
# Check what happens on HTTP — should redirect, not serve content
curl -sI http://target.example.com | head -5
A max-age below 1 year (31536000 seconds) is worth noting. HSTS without includeSubDomains leaves subdomains exposed. HSTS without preload doesn't protect first-time visitors before they've seen the header.
Also check for mixed content using browser developer tools. The console will flag any HTTP resources loaded on an HTTPS page. A more thorough check: intercept responses with a proxy and search for http:// references in HTML source, JavaScript, and CSS.
Testing Password Storage
You generally can't directly inspect how passwords are stored without database access. But there are indirect signals that reveal the hashing scheme in use.
Response time analysis
bcrypt's cost factor is intentional latency. A login request that verifies a bcrypt hash will take 100–300ms on the server. A login that uses MD5 or SHA256 will respond in under 10ms. Measure the time difference between a valid login and an invalid login attempt — if both respond in under 20ms, the application is not using a slow password hash.
# Time a valid login attempt
time curl -s -o /dev/null -X POST https://target.example.com/login \
-d "username=testuser&password=correctpassword"
# Time an invalid login attempt
time curl -s -o /dev/null -X POST https://target.example.com/login \
-d "username=testuser&password=wrongpassword"
Note: this is indirect evidence, not confirmation. A fast response could also mean the user lookup failed before hashing (username enumeration side-channel). Check both a known-valid username with a wrong password and an unknown username.
Password reset flow observation
Password reset flows sometimes reveal storage mechanisms. If the application emails you your existing password in plaintext, it is stored in plaintext — the most severe case. If the reset link doesn't expire or is guessable, that's a separate finding. Observe whether the reset token appears in the URL (logged by servers and proxies) or in a POST body.
Error message analysis
Some applications leak hashes in error responses, debug output, or API responses. Test password reset and profile endpoints for any field that might contain a stored hash value.
Testing for Sensitive Data Exposure
HTTP response headers
Inspect response headers on every endpoint. Look for:
- Missing security headers that enable data leakage: no
Content-Security-Policy, noX-Content-Type-Options, noReferrer-Policy - Verbose server headers exposing version information:
Server: Apache/2.4.41,X-Powered-By: PHP/7.4.3— not cryptographic failures directly, but they appear in the same audits - Set-Cookie without Secure flag — session cookies without
Securewill be transmitted over HTTP if the browser visits an HTTP URL for the same domain - Set-Cookie without HttpOnly flag — session cookies accessible to JavaScript are vulnerable to theft via XSS
# Inspect all response headers from the login endpoint
curl -sI https://target.example.com/login
# Check cookie flags specifically
curl -sc /dev/null https://target.example.com/login -v 2>&1 | grep -i 'set-cookie'
URL parameter analysis
Audit the application for sensitive data passed in query strings. Common findings:
- Session tokens or API keys in
?token=,?api_key=,?auth=parameters - Password reset tokens in URLs (better in a POST body or header)
- PII in URLs:
?email=user@example.com,?ssn=,?dob= - OAuth tokens or codes in redirect URLs that may be logged
Error messages and stack traces
Trigger error conditions deliberately — submit malformed input, access non-existent resources, send invalid content types. Production applications should return generic error messages. Stack traces, SQL queries, file paths, and internal hostnames in error responses are information disclosure findings that often co-occur with cryptographic failures.
JavaScript source analysis
Frontend JavaScript frequently contains hardcoded API keys, tokens, and credentials that belong server-side. Check all .js files loaded by the application for:
# In browser devtools, search loaded scripts for common patterns
# Or download and grep:
curl -s https://target.example.com/static/app.js | grep -iE \
'(api_key|apikey|secret|password|token|private_key)\s*[=:]\s*["\x27][^"\x27]{8,}'
What Automated DAST Tools Catch — and What They Miss
Cryptographic failure testing is one of the stronger areas for automated scanners, precisely because much of it is observable at the network layer. TLS configuration is entirely external — you don't need application-level access to test it.
| Finding type | Automated detection | Notes |
|---|---|---|
| TLS 1.0 / TLS 1.1 support | Excellent | Fully automated; protocol negotiation is deterministic |
| Weak or NULL cipher suites | Excellent | Enumerable by probing the TLS handshake |
| Missing HSTS header | Excellent | Simple header presence check |
| Missing Secure / HttpOnly cookie flags | Good | Requires authenticated session to see session cookies |
| HTTP login form (cleartext credentials) | Good | Scanner must recognise the form as a login form |
| Self-signed or expired certificates | Good | Certificate inspection is standard |
| Sensitive data in URL parameters | Moderate | Scanner must know which parameter values are "sensitive" |
| Hardcoded secrets in JavaScript | Moderate | Pattern matching helps; novel key formats are missed |
| Password hashing algorithm | Poor | Response time is an indirect signal; confirmation requires source access |
| AES-ECB mode / weak IV usage | Poor | Application-layer encryption choices aren't visible at the HTTP layer |
| Key management failures | Very limited | Keys in config files require source or filesystem access |
The pattern is consistent: anything observable at the network or HTTP layer (TLS, headers, cookies, URLs) is well-covered by automated scanning. Anything inside the application — how passwords are hashed, how data is encrypted at rest, where keys are stored — requires source code review or authenticated access to the application's internals.
How Ironimo Approaches Cryptographic Failure Detection
Ironimo's scanning pipeline covers the externally observable surface comprehensively. For every target, the scanner:
- Enumerates all endpoints across the application, including subdomains and non-standard ports, to ensure TLS configuration is checked everywhere — not just the primary domain
- Tests TLS configuration using the same tooling professional pentesters use: protocol version support, cipher suite strength, certificate validity and chain, and known protocol vulnerabilities
- Checks security headers on every response: HSTS presence and configuration,
Content-Security-Policy,X-Content-Type-Options,Referrer-Policy,Permissions-Policy - Inspects cookie flags on authenticated sessions:
Secure,HttpOnly,SameSite - Detects sensitive data patterns in HTTP responses, error messages, and JavaScript source: API key formats, token patterns, and PII markers
- Checks for HTTP-to-HTTPS redirect behaviour and verifies HSTS is enforced with adequate
max-age
Where Ironimo cannot reach without source access — password hashing algorithms, at-rest encryption choices, key storage — findings include guidance on what to verify manually and what questions to ask your development team.
Key Takeaways
- Cryptographic Failures (A02) covers transport security, algorithm choices, key management, and data classification — test all four, not just TLS
- testssl.sh and nmap ssl-enum-ciphers cover the TLS surface systematically; run them against every endpoint, not just port 443 on the primary domain
- HSTS without
includeSubDomainsand a longmax-ageis partial protection at best — check the header parameters, not just its presence - bcrypt response time is a useful signal for password hashing quality, but it's indirect — source code review confirms it
- Sensitive data in URLs, logs, and cookies is often a classification failure rather than an algorithm failure — look for it everywhere, not just in crypto-adjacent flows
- Automated tools have strong coverage of the network-observable layer; application-layer crypto choices need manual review or source access
Ironimo tests your application's TLS configuration, security headers, cookie flags, and sensitive data patterns using the same Kali Linux toolset professional pentesters run against production targets — across every endpoint, not just your homepage.
Schedule on-demand or recurring scans. Each finding includes the exact request, the response that confirms it, and a remediation path your team can act on immediately.
Start free scan