9

Related to, of course, the heartbleed vulnerability, I've been reading the news about the worst case scenario for this attack being the extraction of the SSL private key, because, of course, this would allow the attacker to decrypt all traffic to and from the compromised server, including [probably, depending on forward secrecy] any traffic that's been captured and stored somewhere.

This got me thinking, assuming the worst case scenario, that your Heartbleed vulnerable server had echoed back memory containing your private key... how would the attacker be able to differentiate it from other memory contents, or uninitialized memory, or what have you? Is there a header/footer, or a telltale pattern in the key data itself? I know some RSA Key forms (PEM/base64) have headers/footers in the file (-----BEGIN FOO BAR KEY----- and -----END FOO BAR KEY-----), though I'm having trouble imagining those strings loaded into memory. Is it maybe given away by having something recognizable using a pointer to it?

It doesn't seem like something you can brute force (trying every X bit combination of memory content against 64 KB of memory seems like it would generate an astronomically large number of permutations).

So, how's it done? How is a cryptographic key in memory recognized as a cryptographic key? And in a related question, is the answer different or the same for a symmetrical crypto key? (such as you might extract with a cold boot attack against a system using full disk encryption, for example.)

3 Answers 3

16

Yes. Most private keys have an easily identifiable format.

If its say an RSA private key generated with openssl, they have a specific format e.g., will always start with the same three bytes depending on key size:

30 82 01 (for 768 bit key or MIIB in base64)
30 82 02 (for 1024 bit key or MIIC in base64),
30 82 04 (for 2048 bit key or MIIE in base64),  
30 82 09 (for 4096 bit key or MIIJ in base64).

There are some other types of formats that the private key can be stored in as well.

You can test this yourself with openssl using the commands: openssl genrsa 1024 (1024 means 1024 bit key to see the key in its base64 representation. )

For more documentation on the format see this StackOverflow answer: Where can i find some documentation on the format of an RSA public key?

3
  • Nowadays, with the huge amount of other fields in certs, it's common to see MIIF for 2048, and bare root keys are commonly MIID. Since what follows MII is a length, better to just scan for MII (or 3082) and then see if what comes after is parseable. Aug 31, 2020 at 15:58
  • 1
    Agreed, though private keys (as specified) don't contain cert fields. In ASN.1 30 82 says start sequence with length described in next two bytes; e.g., my 4096 bit private key starting with 30 82 09 28 (MIIJ...) has length is 09 28 (2344 bytes). This is broken down ( tools.ietf.org/html/rfc3447#page-61 ) as a 2 byte version number (stating not multi-prime RSA), a 4096 bit modulus, 17 bit public exponent (e=65537), 4096-bit private exponent, two 2048-bit primes, and three 2048 bit numbers related to Chinese Remainder Theorem.
    – dr jimbob
    Aug 31, 2020 at 20:30
  • 1
    @SilverbackNet, so if you convert bits to bytes (divide bits by 8) and add 4 byte headers (per ASN.1), it works out as 2 + 512 + 2 + 512 + 256 + 256 + 256 + 256 + 256 + 9*4 = 2344 which matches the SEQUENCE length specified. Again for certs the length will be different, but had specified RSA private keys (and yes, will be different for multi-prime RSA which is much less commonly used than two prime RSA).
    – dr jimbob
    Aug 31, 2020 at 20:34
2

As an addendum to dr jimbob's answer:
There are utilities that look for these patterns and try to extract keys that way.

Disclaimer: I have not tried any of these utilities. This post is just a nicer version of the links posted by user "void-star" on HN. (See below.)

Further reading

0

As a (nother) addendum to StackzOfZtuff and dr jimbob's answer's

the Adi Shamir et al. paper Playing hide and seek with stored keys takes a very different approach, than looking for headers

The Shamir approach relies on comparing blocks of data in the complete memory string (i.e. dump the entire contents of memory / disk as a string) and seeing if they are mathematically related to a previously known public key.

In order to find keys where there isn't a previously known public key, a check was made to check the entropy of the data.

Since we know that key data has more entropy than non-key data, one way to locate a key is to divide the data into small sections, measure the entropy of each section and display the locations where there is particularly high entropy

Because keys are intentionally random, this data stands out against a backdrop of data that isn't as random. This attack has the advantage that it should be possible to locate any cryptographic key.

Our techniques seem to be applicable to a wide variety of other public key schemes, in addition to the RSA scheme.

As dr jimbob pointed out, Tobias Klein took the approach of looking for the headers

The following shows the hexadecimal representation of this ASN.1 syntax:
30 82 ?? ?? - SEQUENCE (30 82), length of the SEQUENCE (?? ??)
30 82 ?? ?? - SEQUENCE (30 82), length of the SEQUENCE (?? ??)

As all certificates should be represented in this syntax, we have a pattern to search for.

With full disk encryption you would no longer be able to search for random data on the disk, because everything would be random. You would also no longer be able to search for headers because they would be encrypted.

However once the machine is booted, it would be possible to read keys directly from memory by either of these techniques. This is even easier for a VM (see my answer here)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .