Challenge Overview
Category: Network
Files: dist-gate_to_the_past.zip (an SSHv2 packet capture)
The capture is an SSHv2 session from OpenSSH_4.3p2 Debian-9etch3. That Debian/OpenSSL era is the giveaway: it’s affected by CVE-2008-0166, where OpenSSL’s PRNG had only process-ID-scale entropy. OpenSSH uses that PRNG for Diffie-Hellman private exponents, so the client/server DH secret can be recovered by enumerating the weak PRNG outputs.
1. Negotiated Algorithms
From the plaintext handshake:
- KEX:
diffie-hellman-group-exchange-sha1 - Cipher:
aes128-cbc - MAC:
hmac-md5 - Compression:
none
The handshake also exposes:
- Client DH public value
e - Server DH public value
f - 1024-bit safe prime
p, generatorg = 2 - Client request:
min = 1024,n = 1024,max = 8192
2. Recovering the Client DH Private Exponent
I reproduced the vulnerable Debian OpenSSL PRNG and brute-forced two parameters:
- the process ID used to seed the PRNG, and
- a small amount of “prior” random-byte consumption (bytes pulled from the PRNG before the DH exponent draw).
The unique matching candidate for the client public key was:
pid = 13prior RAND_bytes consumption = 11 bytesx = 0xbd886dabb7951ae7495f31444753098d07db09b9357d8df2795f88012158a351This satisfies:
pow(2, x, p) == eOnce x is known, the SSH shared secret falls out:
K = pow(f, x, p)3. Computing the Exchange Hash
One detail mattered enough to call out: the SSH exchange hash uses the SSH_MSG_KEXINIT payloads without their packet padding. Including the padding bytes yields the wrong exchange hash and the wrong derived keys.
With the right payload boundaries, the exchange hash is:
H = 3800bc5ef9859a61c28bfcc4fdd43b5bc9bcfdcaThis also verifies against the server’s RSA signature — the decrypted signature contains SHA1(H):
825b5504f079b2466ad9f9772aa9dec3161d5da24. Key Derivation and Decryption
Using RFC 4253 key derivation with session_id = H:
IV_c2s = SHA1(K || H || "A" || session_id)IV_s2c = SHA1(K || H || "B" || session_id)key_c2s = SHA1(K || H || "C" || session_id)key_s2c = SHA1(K || H || "D" || session_id)mac_c2s = SHA1(K || H || "E" || session_id)mac_s2c = SHA1(K || H || "F" || session_id)Decrypting both directions with AES-128-CBC and verifying every packet with HMAC-MD5 gives clean plaintext.
The recovered client command was:
echo "flag: FLAG{n3v3r_f0rg3t_13g4cy_bug5}"The server replied:
flag: FLAG{n3v3r_f0rg3t_13g4cy_bug5}Flag
FLAG{n3v3r_f0rg3t_13g4cy_bug5}