[Cryptography] Determining TLS session keys from the hypervisor
leichter at lrw.com
Sun Jun 12 06:34:12 EDT 2016
Very elegant and powerful attack in which code running in a hypervisor can extract the keying material for any TLS session a guest establishes. The basic ideas:
1. Use packet filters to monitor traffic and recognize the beginning of TLS connections - in particular look for Server Hello and Client Finished messages. Observe that (a) at the time of Server Hello, the keying material *is not* present in the VM's memory; (b) at the time of Client Finished, the keying material *is* present in the VM's memory; (c) Client Finished is encrypted using the agreed-upon key; (d) Client Finished contains some known plaintext.
2. In order to support efficient snapshots of the memory state of running VM's, hypervisors support the ability for the hypervisor to receive a stream of pages as they become "dirty" (i.e., are modified). So at the time of Server Hello, subscribe to receive such a stream and save it; at the time of Client Finished, disconnect the stream. Since the keying material was written to memory somewhere between those two messages, it must appear somewhere in the pages saved. (Experimentally, this is typically a few megabytes of data.)
3. The TLS key block - containing all the keying material - has a fixed length and layout, and appears somewhere in the saved data. Try all possible positions for it, using the known plaintext of the Client Finished message to test the proposed key. (This is the only place we assume anything about the code running in the attacked machine: We need to know what a TLS key block looks like. There aren't that many TLS implementations around, and which one is being used should be easy enough to determine by once examining the VM's memory - or, for that matter, the file that was exec'ed to start the server - so this is no big deal.
Depending on the ciphersuite chosen, some straightforward attacks are linear in the number of possible keys while others are quadratic (because, e.g., one needs to guess at the IV as well). But there are clever optimizations that reduce some of the quadratic attacks down to linear time. Ironically, AES-GCM - the most widely used ciphersuite - takes linear time and doesn't even require known plaintext: The authentication tag can be leveraged to validate the block directly.
The attack can be generalized to cover the more realistic case in which a the server being attacked is initiating multiple simultaneous connections; things get slightly more expensive but all the keys are extracted. Typical "brute force" times are a couple of seconds, and of course a brute force attack is trivially parallelizable.
The attack slows the server a bit, but the additional time per connection is a few milliseconds - very hard to detect among network overheads.
Defenses are not clear. A library could randomize the layout of the key block it uses per connection. It would have to compute and store the parameters *before* Server Hello or the attacker would simply target that material. But this strikes me as an expensive defense that would only slow the attacker down a bit.
More information about the cryptography