Watching the industry respond to the Heartbleed vulnerability has been fascinating. This bug had widespread impact with thousands of servers left vulnerable, numerous private keys compromised, and companies quick to jump on the bandwagon to gain a marketing advantage. All this activity rekindled the conversation around the security offered by open source projects and the lack of financial support provided to the projects used in critical infrastructure.
While all this is going on, researchers are upping their efforts to review OpenSSL source code to find additional vulnerabilities. This left us wondering: “What will we find next?” Well, it didn’t take long for another critical OpenSSL vulnerability to show up in the queues at the Zero Day Initiative. Jüri Aedla is credited for the original discovery of this vulnerability. He recently made news by successfully compromising Mozilla Firefox during this year’s Pwn2Own contest. We enjoy analyzing his work and knew immediately it would be an exciting case.
Let’s discuss the vulnerability itself:
The issue exists wholly within ssl/d1_both.c and occurs when handling Datagram Transport Layer Security (DTLS) fragments. DTLS has a fragmentation mechanism to break up large messages for UDP. Each fragment contains a 3-byte length field, which should be the same for all fragments in a message. OpenSSL incorrectly assumes that all DTLS fragments specify the same message size. Specifically, it trusts that the message length specified within the header of the first fragment will be invariant across all fragments. Here is an example packet that demonstrates the issue:
Another quick observation is that the Wireshark protocol decoder highlights the mismatch of the length values in the DTLS fragments as a protocol error. Unfortunately, OpenSSL did not recognize this as an error condition.
The relevant source code is below (as of this commit):
1. Read first fragment header.
2. Check if it is a fragment. Fragment Length of 1 < Length of 2.
3. Allocate space for new message based on length in header, as it’s the first fragment.
4. Allocate a 2-byte buffer for the whole message.
5. Read in the 1-byte from the first fragment.
6. Read second fragment header.
7. Check if it is a fragment. Fragment Length of 986 < Length of 987.
8. Read in the 986-bytes second fragment into a 2-byte buffer.
Just sending this single UDP packet results in the application segfaulting and causing a denial-of-service condition, but more malicious things are possible. As the length field is 3-bytes wide, it is theoretically possible to write up to 2^24 bytes of data to the process using this vulnerability. An attacker could leverage this issue to corrupt adjacent metadata, and possibly execute code in the context of the process using OpenSSL.
The OpenSSL code does some sanity checking on the length fields in the DTLS fragments but, unfortunately, the check occurs too late and could be bypassed. The developers even left a prophetic comment in the code about what would happen if the validation failed.
So, why is this vulnerability interesting beyond just the technical aspects?
According to the commit logs, Robin Seggelmann introduced this vulnerability into the OpenSSL code base four years ago. Yes, Robin Seggelmann is also responsible for introducing the Heartbleed vulnerability. Two big vulnerabilities introduced by the same developer. Seggelmann is not completely to blame, of course. OpenSSL is an open source project. The ‘many eyes’ that look at this code failed to catch this bug, but a new breed of individuals are looking at this code…especially at Seggelmann’s code. This code is now known for having vulnerabilities. There is blood in the water. For the individuals auditing his code, the Zero Day Initiative will happily handle the work that goes into disclosing those vulnerabilities and reward you for your efforts.
[Note: The team at HP TippingPoint’s DVLabs talks about this vuln and their customer protection here. Be sure to check it out!]