Двойной хэш (Double Hash)
Двойной хэш (Double Hash)
Platform: hackerlab | Category: Crypto | Type: Challenge | Difficulty: Medium | OS: Linux | Author: XESXOR | Date: 2026-01-02 | Status: Solved Techniques: Double encryption with identical keys, Hex encoding/decoding, RC4 stream cipher XOR cancellation attack, Web service interaction
Summary
Task: Flask web service with double RC4 encryption where user controls both keys. Solution: XOR cancellation attack - using identical keys (key1 == key2) causes the stream cipher to cancel itself, returning the flag in plaintext.
Двойной хэш (Double Hash) — hackerlab
Description
Один ключ хорошо, а два... хуже?!
A Flask web service with double RC4 encryption of the flag.
Analysis
Service Source Code
python read-only • copy allowedimport random from Crypto.Util.number import * key = ? FLAG = ? @app.route('/double_hash/encrypt/<key1>/<key2>/') def decrypt_flag(key1, key2): try: key_1 = bytes.fromhex(key1) key_2 = bytes.fromhex(key2) except: return {"error": "non-hexadecimal"} nonce = os.urandom(4).hex().encode() nonce1 = pbkdf2_hmac('sha256', key_1, b'salt', 100000, dklen=32) + nonce nonce2 = pbkdf2_hmac('sha256', key_2, b'salt', 100000, dklen=32) + nonce tempkey1 = SHA.new(key+nonce1).digest() tempkey2 = SHA.new(key+nonce2).digest() round1 = ARC4.new(tempkey1) firstEncryption = round1.encrypt(FLAG) round2 = ARC4.new(tempkey2) finalEncryption = round2.encrypt(firstEncryption) result = hexlify(finalEncryption + nonce).decode() return {"result": result}
Encryption Algorithm
- Accepts
key1andkey2in hex format - Generates random
nonce = os.urandom(4).hex().encode()(8 bytes) nonce1 = PBKDF2(key1, 'salt', 100000) + noncenonce2 = PBKDF2(key2, 'salt', 100000) + noncetempkey1 = SHA1(server_key + nonce1)tempkey2 = SHA1(server_key + nonce2)- Double encryption:
ARC4(tempkey2).encrypt(ARC4(tempkey1).encrypt(FLAG)) - Returns
hex(ciphertext + nonce)
Vulnerability: XOR Cancellation
RC4 (ARC4) is a stream cipher that works via XOR:
ciphertext = plaintext XOR keystream
If key1 == key2:
nonce1 == nonce2(identical PBKDF2 output)tempkey1 == tempkey2(identical SHA1 hash)- Both RC4 instances generate identical keystream
Double encryption with the same key:
round1 = FLAG XOR keystream
round2 = round1 XOR keystream = FLAG XOR keystream XOR keystream = FLAG
XOR property: A XOR B XOR B = A
Result: the flag is returned in plaintext!
Solution
Exploitation
bash read-only • copy allowedcurl -s "http://62.173.140.174:11003/double_hash/encrypt/00/00/"
Response:
json read-only • copy allowed{"result": "434f444542597b443075626c335f683473685f336e637279707469306e7d3565393865653835"}
Decoding
python read-only • copy allowedresult = '434f444542597b443075626c335f683473685f336e637279707469306e7d3565393865653835' # Last 16 hex characters = nonce (os.urandom(4).hex().encode() = 8 bytes) nonce_hex = result[-16:] # '3565393865653835' encrypted_hex = result[:-16] # '434f444542597b443075626c335f683473685f336e637279707469306e7d' # Decode the flag flag = bytes.fromhex(encrypted_hex).decode() print(flag) # CODEBY{REDACTED}
Theory
Why Double RC4 Encryption is Dangerous
Unlike block ciphers (AES), where double encryption increases complexity, XOR-based stream ciphers have a self-inverse property:
E_k(E_k(m)) = m XOR keystream XOR keystream = m
Correct Implementation
For secure double encryption you need:
- Different keys (key1 != key2)
- Or different nonce for each round
- Or use a block cipher in CBC/GCM mode
Alternative Solutions
Any Identical Keys
bash read-only • copy allowedcurl "http://62.173.140.174:11003/double_hash/encrypt/deadbeef/deadbeef/" curl "http://62.173.140.174:11003/double_hash/encrypt/41414141/41414141/"
All variants with key1 == key2 will return the flag in plaintext.