I think it's probably a piece of dead code at this point, but there might be some legacy stuff using it (with an old version of OpenSSL), which could lead to a vulnerability. Regardless, the function should probably be rewritten or removed.
Yeah, I'm thinking it's dead code. It's not exposed in modern OpenSSLs, and I can't find any services we use (Pure-FTP, httpd, etc) that use this function.
I made a patch to ruby swapping the memcmp for CRYPTO_memcmp, which should be constant-time. I'm checking to see that I didn't break the build, after which I'll make a pull request to https://github.com/ruby/ruby. Then it'll be up to the ruby developers, who probably have better insight into this than me, to accept or decline it.
Session IDs themselves are public; namely they may be exchanged in the plain text as part of an initial TLS handshake. They are used for session resumption to look-up confidential (e.g. keying) information that should be stored in a protected manner by the TLS peers.
Given that the session ID is exchanged in plaintext, I'm definitely not seeing the security risk here. At best, you could potentially use a timing attack to recover the contents of a session ID, but you can already get that by sniffing the network. And in any case, even if you did get that, I don't think there's anything interesting you could do with it.
Heartbleed I just about understand, as despite this not being my field, smart people successfully summarized it in an easily digestible way so that I could even explain it to my mum. Can someone ELI5 this too please?
Basically, measure the time difference in the memory comparison. Typically, comparisons will short-circuit. That is, stop as soon as a difference is detected. But this is a problem for security situations like key comparisons. If 10 out of 20 bytes match, it will take a little bit longer to compare then if 5 out of 20 bytes match. With enough iterations, the key can be recovered due to these differences in time. The correct solution is to use a constant time comparison that always runs through the entire sequence of bytes.
On many versions, memcmp will return exactly when it sees a difference between the two buffers. Because it returns immediately one can figure out what byte it failed at due to timing and construct the correct input.
Some others have pointed out that it's a static function, which I stupidly overlooked. Others have pointed out it's not really used anymore so the title doesn't accurately reflect the issue. -- I will probably delete this thread.
It wasn't static for older versions of OpenSSL, so this still might be an issue if someone was using that function with the assumption of it being constant-time.
memcmp compares two blocks of memory byte-by-byte. If the first two bytes don't match, the function can return early, otherwise it has to check the next byte. By measuring the execution times for all 256 possible bytes, one should be able to guess the first byte. Repeat this for the length of the memory being compared, and you should be able to essentially read the entire block of memory you're being compared against.
These attacks are usually done over a fast connection (maybe buy a machine in the same datacenter as your target), and through lots of measurements averaged together and measured for statistical significance.
We don't know where this function is used, so this might actually be a non-issue. We need someone more familiar with OpenSSL to comment.
What kind of connection is fast enough to detect the difference of a single loop iteration inside memcmp()? I get that this is type of attack is possible if you share the same machine with the attacker. But over the network? Are there any credible sources for this?
You don't need fast — you need predictable latency, that's all. Once you have predictable latency, you can work out compute time. And latency can become predictable through a large number of samples.
My point is that to receive a single packet, you have an external interrupt, you go through the device driver, the ip stack, etc. And in all that you are looking for a difference of a single cycle. That won't work. Even with a zero latency network. There is just too much code involved.
You can measure differences of thousands or maybe even hundreds of cycles, but not single cycles. That's below the noise level of a modern computer.
Thanks for the link. They claim that they can measure differences as small as 100ns, which is pretty impressive. A single iteration in memcmp is still a lot faster: about 1ns. I have a hard time to see how there is a realistic remote attack in this case.
> What kind of connection is fast enough to detect the difference of a single loop iteration inside memcmp()?
Any, really, if you hit it with enough copies of each potential input so that you can get enough results to separate the timing difference from the noise. Though the faster, the more samples you can do per unit time, and the closer in network topology, the less sources of variability in latency that make it take more samples you'll have. At least, that's my understanding.
No, there's a threshold below which you can't effectively distinguish noise from signal even with many samples; theoretically, you can try to overcome this problem with more samples, but there are practical limits, and often actual constraints on the number of samples you can collect and the window of time you have to collect them.
Read Crosby and Wallach's "Opportunities and Limits" paper; the shorthand result of the paper is that across Ethernet you have a window of 100ns, and across an IP network something closer to 30us. The memcmp distinguisher is well below the IP network threshold.
This could, in theory, allow discovering IDs of sessions that are either active or cached on the server end. IDs are passed in clear between SSL peers, so being able to recover them doesn't compromise the security of the protocol.
That said, this can be used to estimate the size of the server's session list and to covertly measure and monitor the volume of its activity. This can come handy in some cases, but then splicing into server's Internet connection and passively listening to the traffic would yield the same information with much less fuss.
C memcmp() timing channels are extremely difficult in practice to exploit, even at relatively close proximity to targets, so I'm not sure how practical any of this is.
It's probably not practical, but it doesn't hurt to fix or remove (it's not used internally in OpenSSL) the code anyways. I submitted a pull request to Ruby, where the code was copied to, and is used: https://github.com/ruby/ruby/pull/591 .
Ruby uses a version of it they copied into their source tree. You can't really fault OpenSSL for another project copying one of their internal, static functions. I've never looked at Ruby's code base before. Did they just fork all of OpenSSL?
The code in question is a Ruby FFI wrapper for OpenSSL (not a fork). Originally the function wasn't static, so when OpenSSL made it static, Ruby copied the function implementation to their source tree, as to avoid breaking their API.
Is it actually feasible to do a timing attack using memcpy?
I've been testing a bit locally, as in within the same process, without any luck. I have a hard to seeing how this would work, especially when you add network latency.
Does anyone have any proof-of-concept code that actually exploits memcpy with a timing attack?
41 comments
[ 10.3 ms ] story [ 105 ms ] threadEDIT: I see it exposed in 0.9.8y. Anyone know of anything that builds against this specifically and uses it?
I think it's probably a piece of dead code at this point, but there might be some legacy stuff using it (with an old version of OpenSSL), which could lead to a vulnerability. Regardless, the function should probably be rewritten or removed.
EDIT: It looks like the latest version of Ruby (MRI) actually copied this function from OpenSSL so they could keep using it: https://github.com/ruby/ruby/blob/1aa54bebaf274bc08e72f9ad38...
OpenSSL devs should probably remove this code.
EDIT: For anyone interested: https://github.com/ruby/ruby/pull/591
I don't know of anything that builds against that version specifically but it is the version that is included in OS X as of 10.9 (and possibly 10.8).
On many versions, memcmp will return exactly when it sees a difference between the two buffers. Because it returns immediately one can figure out what byte it failed at due to timing and construct the correct input.
Some others have pointed out that it's a static function, which I stupidly overlooked. Others have pointed out it's not really used anymore so the title doesn't accurately reflect the issue. -- I will probably delete this thread.
These attacks are usually done over a fast connection (maybe buy a machine in the same datacenter as your target), and through lots of measurements averaged together and measured for statistical significance.
We don't know where this function is used, so this might actually be a non-issue. We need someone more familiar with OpenSSL to comment.
Brumley and Boneh's 2003 paper ("Remote timing attacks are practical") on this is the typical reference: http://crypto.stanford.edu/~dabo/papers/ssl-timing.pdf
You can measure differences of thousands or maybe even hundreds of cycles, but not single cycles. That's below the noise level of a modern computer.
Particularly the section titled "You can’t possibly measure that, can you?"
Any, really, if you hit it with enough copies of each potential input so that you can get enough results to separate the timing difference from the noise. Though the faster, the more samples you can do per unit time, and the closer in network topology, the less sources of variability in latency that make it take more samples you'll have. At least, that's my understanding.
Read Crosby and Wallach's "Opportunities and Limits" paper; the shorthand result of the paper is that across Ethernet you have a window of 100ns, and across an IP network something closer to 30us. The memcmp distinguisher is well below the IP network threshold.
That said, this can be used to estimate the size of the server's session list and to covertly measure and monitor the volume of its activity. This can come handy in some cases, but then splicing into server's Internet connection and passively listening to the traffic would yield the same information with much less fuss.
> Not used anywhere though, just a corpse lying around in the code. — Jann Horn
EDIT: I see you made a patch for it. High five!
I've been testing a bit locally, as in within the same process, without any luck. I have a hard to seeing how this would work, especially when you add network latency.
Does anyone have any proof-of-concept code that actually exploits memcpy with a timing attack?