Every once in awhile I get an opportunity to work on a “known” vulnerability, but with very little or even no available technical details. These known vulnerabilities tend to be “known” just to their finder and to the vendor that fixed the vulnerability. We know they exist because an advisory is published, but not much more than that.
From the point where the vulnerability got fixed, no one (researcher or vendor) has any interest in disclosing the vulnerability details – as it is no longer interesting – leaving security researchers with insufficient information to confirm whether this vulnerability affects anyone else beside the specific vendor – and specific vendor version.
This is the point I reached today, where our team wanted to update a test of our vulnerability scanner to check for the exploitability of a certain vulnerability on a new platform. The version indicated it was vulnerable to the problem but there was no way to confirm it as the vulnerability’s technical description was inadequate, and checking only the version is a sure way for multitude of false positives.
With the little information available:
The get_server_hello function in the SSLv2 client code in OpenSSL 0.9.7 before 0.9.7l, 0.9.8 before 0.9.8d, and earlier versions allows remote servers to cause a denial of service (client crash) via unknown vectors that trigger a null pointer dereference.
I was determined to discover what was the “unknown vector” and see whether the product I tested was in fact vulnerable or not.
First step was to understand what the SSLv2 exactly is, and how I can get it – well simple enough here, “openssl s_client” is just what I needed – it was a sample SSL client that utilizes the get_server_hello() function.
Then I needed to create an SSLv2 session, this proved to be a bit more difficult as SSLv2 is now considered insecure and most SSL installations disable it – further Firefox no longer allows connecting to those sites that support it… but apparently Apache 2 haven’t given up on it, and you can turn SSLv2 support quite easily through the SSLProtocol definition.
Once that was available, I launched beSTORM’s auto-learn mechanism and made it capture the SSLv2 traffic – a complete session can be quite extensive but I only needed the first packets as they were the one get_server_hello() function looks into – once this was ready I used the pcap export capabilities to load the captured data into Wireshark – and use Wireshark’s existing dissection to mark which fields where what – who was the length of what, what was a flag, etc.
Then I told beSTORM to start listening on incoming traffic and play around with the values, I mainly concentrated on the following ServerHello parameters:
- Packet Length (total length)
- Session ID Hit (valid value is either set to 0x01 or set to 0x00)
- Certificate Type (it is an enumeration of three possible values)
- Certificate Length
- Certificate Value
- Cipher Spec Length
- Cipher Spec Value
- Connection ID Length
- Connection ID Value
After a few thousands of combinations – taking about 50 minutes – with beSTORM modifying the Session ID Hit (set to 0x00), Certificate Type set to NULL (0x00), Certificate Length equal to 0, Certificate Value set to none, Cipher Spec Length equal to 0, Cipher Spec Value set to none and the default captured values of Connection ID – the openssl client crashed:
Program received signal SIGSEGV, Segmentation fault.
0x0808638d in get_server_hello (s=0x81aed90) at s2_clnt.c:542
542 if (s->session->peer != s->session->sess_cert->peer_key->x509)
Now all I needed was to instruct beSTORM to build a module from it – job done.
From a very vague description to an exploit in about an hour
An exploit can be found at: OpenSSL SSLv2 Client Crash (NULL Reference)