| name | length-extension-attacks-anti-pattern |
| description | Security anti-pattern for hash length extension vulnerabilities (CWE-328). Use when generating or reviewing code that uses hash(secret + message) for authentication, API signatures, or integrity verification. Detects Merkle-Damgard hash misuse. |
Length Extension Attacks Anti-Pattern
Severity: High
Summary
Hash length extension attacks exploit Merkle-Damgård construction vulnerabilities in MD5, SHA-1, and SHA-256. Attackers knowing hash(secret + message) and secret length can compute hash(secret + message + padding + attacker_data) without knowing the secret. This enables appending data to signed messages with valid signatures, completely breaking message integrity and authentication.
The Anti-Pattern
Never use vulnerable hash functions (MD5, SHA-1, SHA-256) in hash(secret + message) construction for MACs. Use HMAC instead.
BAD Code Example
import hashlib
SECRET_KEY = b"my_super_secret_key_16b"
def get_signed_url(message):
signature = hashlib.sha256(SECRET_KEY + message.encode()).hexdigest()
return f"/api/action?{message}&signature={signature}"
def verify_request(message, signature):
expected_signature = hashlib.sha256(SECRET_KEY + message.encode()).hexdigest()
return signature == expected_signature
GOOD Code Example
import hmac
import hashlib
SECRET_KEY = b"my_super_secret_key_16b"
def get_signed_url_secure(message):
signature = hmac.new(SECRET_KEY, message.encode(), hashlib.sha256).hexdigest()
return f"/api/action?{message}&signature={signature}"
def verify_request_secure(message, signature):
expected_signature = hmac.new(SECRET_KEY, message.encode(), hashlib.sha256).hexdigest()
return hmac.compare_digest(signature, expected_signature)
Language-Specific Examples
JavaScript/Node.js:
const crypto = require('crypto');
const SECRET = 'my_secret_key';
function signMessage(message) {
const signature = crypto.createHash('sha256')
.update(SECRET + message)
.digest('hex');
return signature;
}
const crypto = require('crypto');
const SECRET = 'my_secret_key';
function signMessageSecure(message) {
const signature = crypto.createHmac('sha256', SECRET)
.update(message)
.digest('hex');
return signature;
}
function verifySignature(message, signature) {
const expected = signMessageSecure(message);
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
Java:
import java.security.MessageDigest;
public class InsecureSigning {
private static final String SECRET = "my_secret_key";
public static String signMessage(String message) throws Exception {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
String combined = SECRET + message;
byte[] hash = digest.digest(combined.getBytes());
return bytesToHex(hash);
}
}
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest;
public class SecureSigning {
private static final String SECRET = "my_secret_key";
public static String signMessage(String message) throws Exception {
Mac hmac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKey = new SecretKeySpec(
SECRET.getBytes(), "HmacSHA256");
hmac.init(secretKey);
byte[] hash = hmac.doFinal(message.getBytes());
return bytesToHex(hash);
}
public static boolean verifySignature(String message, String signature)
throws Exception {
String expected = signMessage(message);
return MessageDigest.isEqual(
signature.getBytes(),
expected.getBytes()
);
}
}
Detection
- Find hash(secret + message) patterns: Grep for concatenation before hashing:
rg 'hashlib\.(md5|sha1|sha256)\(.*\+' --type py
rg 'crypto\.createHash.*update.*\+' --type js
rg 'MessageDigest.*update.*\+' --type java
- Look for
hash(key + data) or hash(data + key) patterns
- Identify vulnerable hash functions for MACs: Search for signing without HMAC:
rg 'hashlib\.(md5|sha1|sha256)' --type py | rg -v 'hmac'
rg 'crypto\.createHash\(' --type js | rg -v 'createHmac'
rg 'MessageDigest\.getInstance.*MD5|SHA-1|SHA-256' --type java | rg -v 'Mac\.getInstance'
- Audit signature generation: Find custom MAC implementations:
rg 'signature.*=.*hash|mac.*=.*hash' -i
- Check API signatures, token generation, cookie signing
- Use static analysis: Run tools to detect weak crypto:
- Semgrep:
python.lang.security.audit.hashlib-weak-hash
- Bandit:
B303 (MD5/SHA1 usage)
Prevention
Related Security Patterns & Anti-Patterns
References