Most vulnerabilities in COTS software are quite blatant about their root causes and direct in their impact. A remote code execution vulnerability can be traced to a low level programming error and its immediate effect is likely an 0wned machine, or the next billion dollar self-propagating malware. Once in a while, a new extremely creative type of bug is introduced that defies this pattern. The flaw in the OpenSSL random number generator that affected Debian and Ubuntu is one of those rarities.
The short version: Debian developers attempted to fix a problem in OpenSSL that was flagged by static analysis software. (For other takes on the problem: my colleague Ben Laurie has taken the Debian maintainers to task and added some clarifications about the response, XKCD has neatly summed up the issue with a comic strip and Garntner argued that this incident is indicative of a deeper problems in open-source, just in time for a Coverity report that gave glowing reviews to open source projects for fixing issues identified by their technology.) It turned out the fix was much worse than the ailment
- Motivation: specific problem flagged by the automatic analysis of source code was an instance of using uninitialized memory– something that ought not occur in an ordinary application and is almost always a bug. But a library implementing cryptographic functionality has unusual requirements. In this case the OpenSSL designers were intentionally using uninitialized memory to seed the randomness pool. C/C++ language lawyers will jump up and down at this point screaming that use of uninitialized variables on the stack is undefined by the language. “Undefined” meaning that the compiler is free to optimize out the code, insert an easter egg, cause the application to crash if it reaches that instruction etc. Pragmatically speaking on most CPUs, operating systems and compilers that OpenSSL will likely reach, the memory ends up retaining the junk that was written last time, and this unpredictability is exactly what is required for randomness.
- Neglected wisdom: important point is that the bug was not causing OpenSSL to crash or misbehave. In the worst case, the memory region contained predictable data such as all zeroes, so there was no benefit in seeding a randomness pool with that. No problem because there were many other sources of randomness used. This is a good time to remember the classic engineering adage: “if it ain’t broke, don’t fix it.” Debian developers did “fix” it, but in doing so they removed the addition of all entropy to the pool, instead of simply removing the one instance that was questionable.
- Outcome: OpenSSL random number generator was completely broken. This is a major problem when dealing with cryptography. Everything depends on keeping secrets; encryption only works to protect data from people who do not have the decryption key. When keys are not just random patterns but generated according to a very predictable pattern, they are no longer a secret. The surprising part is that the code did not have a “vulnerability” in the classical sense: OpenSSL would not crash on malformed data because of this, it would not start running somebody else’s code or cause the machine to become the latest inductee into a botnet. A security researcher looking for yet another buffer overrun would be disappointed to realize that nothing of the sort was introduced as a result of the Debian update.