Yesterday a severe bug in the open source OpenSSL code was discovered which allowed recovery of private keys for sessions. This bug appears to allow the attacker to bypass the TLS protection entirely and decrypt the session. This is quite a huge bug since it affects a large proportion of HTTPS connections on the web and essentially allows an attacker to view them in plaintext to recover data transferred including sensitive data like passwords etc.
So what was the culprit for this bug? Well Sean Cassidy's blog about programming covers the bug in some detail and makes some recommendations for the future. In a nutshell, the issue is an unchecked C memcpy call that has overrun its bounds, thereby copying not just the data intended but a chunk of other allocated data. Exactly what will turn up in this copied data will be hard to predict and sometimes this may not lead to anything much useful, but sometimes it seems it can include the private key for the session.
Having spent a lot of my university days and a bunch of my earlier working life programming C then later switching primarily to Java this doesn't really surprise me a lot. C is a hard language to write tight programs in and it reminds me of various bugs I've seen in C code throughout my working life. Some of this C code was written by very competent professional programmers yet still included bugs that could crash the entire process due to a bug like the one above. A simple bug like the one above, even for someone used to writing C, can easily slip by on an off day. Including a simple error like this in security code like OpenSSL can lead to bad things and although there are ways to mitigate the probability of issues like this there isn't any magic panacea. Except perhaps for Sean's three recommendations:
- Pay money for security audits of critical security infrastructure like OpenSSL
- Write lots of unit and integration tests for these libraries
- Start writing alternatives in safer languages
The third one here is the interesting one that a lot of people seem to have forgotten. C was created a long time ago and was created a fairly low level language. You can do a lot in it but you don't get a lot of help from the language and you don't get a lot of protection from yourself. You get a lot of control at a low level but with that control comes the responsibility to manage a lot of detail that can derail things badly if you get it wrong.
Java was created later and is fundamentally a lot more protective than C. The memcpy bug can't exist in Java because you don't get access to memcpy and memory management is taken out of the picture by the garbage collector.
The garbage collector has had its fair share of criticism for introducing delays (although again there are ways to smooth this out) but like Java in general it's easy to take for granted or just plain forget about the benefits it provides.