Intro
The task consisted of a 19kB pcap file with a single complete TLS conversation between a client and an HTTPS server (using DHE_RSA), and a rather laconic description - "just break TLS". Well, since you asked…
Poking around
Shortly after opening the file in Wireshark intersting details surface. While the server looks absolutely valid, the client seems to have a rather unusal random number generator. The 0x20 byte long random nonce sent in the Client Hello message is:
0000000: 4469 4865 2031 3333 3720 3133 3337 2031 DiHe 1337 1337 1
0000010: 3333 3720 3133 3337 2031 3333 3720 3133 337 1337 1337 13
Since that looks very non-random, perhaps the client exponent is easy to figure out?
We can get the Diffie-Hellman parameters p and g from the Server Key Exchange mesage, we also have gx from the Client Key Exchange:
4a771bbd30b56bb87089a665976efc66363448588236d6f61e64e7dfaf54
b187df22337a75930d622b71fc88fb4f5d4af2384e8f0e4a11c967d699f3
05144c369207990053cb2d5e70e596aea4b5b1ac2c274ae08e1eb1bb1d78
eb3b9fd3702d78610b15d39352cbf748919d6930245f4d3e4fc9f48504a1
5e132f08b9c50fb9
So now that the client's private exponent has been recovered, it's time to decrypt the session…
Decryption
Wireshark comes with a built-in SSL decryption facility. What it needs is a Session ID and a Master Secret. The Session ID is (as this is a new session) sent in the Server Hello message, so we have that. We also have the client secret (1337), the generator (2), the prime and the server public key (gy). This allows us to compute gxy, the Pre-Master Secret, by simply raising the server public key to the 1337-th power, mod p.
The Master Secret is computed - according to TLS specs - as PRF(premaster_secret, "master secret", Client Random + Server Random)[0..47], the "+" being string concatenation, and PRF defined someplace else in the same RFC.
Luckily we have all of those, and there is a compliant implementation of the PRF function in the tlslite python library. Plugging in the appropriate values, the master secret is obtained:
The Master Secret is computed - according to TLS specs - as PRF(premaster_secret, "master secret", Client Random + Server Random)[0..47], the "+" being string concatenation, and PRF defined someplace else in the same RFC.
Luckily we have all of those, and there is a compliant implementation of the PRF function in the tlslite python library. Plugging in the appropriate values, the master secret is obtained:
4B02C246E50DE1CEA408018AE53F3C78386356A3D4C196E2FC9DE58079F5C57ED4698925E5BE507E315304A81B8AF2AC
Since RUCTF_ILoveToHackTLS was indeed the correct flag, this concludes the write-up.
Hi,
ReplyDeleteCould you please to upload the challenge file ?
Thanks
https://drive.google.com/file/d/0Bz8mM2W3uK9nR2VLa1Z6cUdUdkk/edit?usp=sharing ← here you go. Additionally a message from the organizers: “we will publish all our tasks on Github (https://github.com/Hackerdom) after Quals Afterparty.”
ReplyDeleteHi! Nice review!
ReplyDeleteHere is my solution: https://alexbers.com/ructf2014_quals/crypto300.py
---
Alexander Bersenev, author of this task