Broken cryptography occurs when applications use cryptographic algorithms, hashing functions, or encryption methods that are mathematically broken, cryptographically obsolete, or provide insufficient security. This includes:
When cryptography is broken, it provides a false sense of security. Data appears encrypted, but attackers can decrypt it trivially or bypass the protection entirely.
Real-World Attack Scenarios
Scenario 1: DES Encryption (56-bit) in Modern Applications
An e-commerce site encrypts credit card numbers using DES:
Cracking can try millions of passwords per second on GPU
8-character password cracked in seconds
Billions of password combinations tested in minutes
The attack:
Attacker has password database with 1-iteration hashes:
Result:
All passwords cracked
Complete compromise
The fix: Use bcrypt with proper rounds:
Finding it: Look for hash functions with < 100,000 iterations. Search for PBKDF2 with low iteration count. Check password hashing code for iteration count.
Scenario 6: RSA Encryption Without OAEP Padding (CWE-780)
An application encrypts data with RSA but doesn't use proper padding:
# Attacker captures encrypted credit cards from database
# Brute force 56-bit key space
hashcat -m 14000 encrypted_cards.txt -a 3 ?a?a?a?a?a?a?a?a
# Within hours, all cards decrypted
# Fraudulent charges across all credit cards
User A: summer2024 → hash
User B: summer2024 → same hash
Attacker knows two users have identical passwords
const bcrypt = require('bcrypt');
async function hashPassword(password) {
const salt = await bcrypt.genSalt(10);
return await bcrypt.hash(password, salt);
}
// Even identical passwords produce different hashes
import hashlib
def hash_password(password):
salt = "fixed_salt_1234" # WEAK - same for all passwords
return hashlib.pbkdf2_hmac('sha256', password.encode(), salt, 100000)
import hashlib
import os
def hash_password(password):
salt = os.urandom(32) # Random salt for each password
return hashlib.pbkdf2_hmac('sha256', password.encode(), salt, 100000)
def hash_password(password):
# Fast but insecure
return hashlib.pbkdf2_hmac('sha256', password.encode(), salt, 1)
# Crack with hashcat on GPU
hashcat -m 10000 hashes.txt /usr/share/wordlists/rockyou.txt
# Speed: 1 billion hashes per second
# 8-character password cracked in < 1 second
# Dictionary attack covers most users in minutes
import bcrypt
def hash_password(password):
# Minimum 10 rounds, preferably 12+
salt = bcrypt.gensalt(rounds=12)
return bcrypt.hashpw(password.encode(), salt)
# Each round doubles computation time
# Makes GPU attacks impractical
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
def encrypt_data(data, public_key):
# VULNERABLE - using raw RSA without OAEP
cipher = PKCS1_v1_5.new(public_key)
encrypted = cipher.encrypt(data)
return encrypted
# Attacker modifies ciphertext slightly
# Sends to server
# Observes if decryption succeeds or fails
# Each success/failure reveals 1 bit of information
# Repeat millions of times to recover plaintext
import base64
def "hash" password(password):
# NOT A HASH - This is just encoding!
return base64.b64encode(password.encode()).decode()
# password123 → cGFzc3dvcmQxMjM=
Card A encrypted: 4f3b2a1c... 4f3b2a1c... (repeating blocks)
Card B encrypted: 7f8c9d2e... 7f8c9d2e... (different repeating)
Card C encrypted: 4f3b2a1c... 4f3b2a1c... (same as Card A)
Attacker knows Cards A and C are identical!
from Crypto.Cipher import AES
import os
def encrypt_credit_card(card_number):
iv = os.urandom(16)
cipher = AES.new(key, AES.MODE_GCM, nonce=iv)
encrypted = cipher.encrypt(card_number)
return iv + encrypted # Send IV with ciphertext
from cryptography.fernet import Fernet
# or
from Crypto.Cipher import AES
# AES-256-GCM
cipher = AES.new(key, AES.MODE_GCM)