Posted by Synopsys Editorial Team on March 7, 2014
Recently, Apple released a patch for a bug in its SSL handshake implementation on iOS and Mac OS X that allowed attackers to intercept SSL traffic originating from vulnerable devices. It turns out that the GnuTLS library also contained a bug that was patched on February 27, 2014; this bug also allows attackers to intercept SSL traffic. Let’s take a look at the GnuTLS issue.
The short story is that the function that performs certificate signature verification (among other things) in GnuTLS sometimes returns a non-zero value if an error occurs. The caller assumes that only a return value of zero indicates an error. So, the caller assumes that certificate signature verification passed when in reality it did not.
To exploit this vulnerability, the attacker would typically need to be on the same LAN as the victim with an application that uses a vulnerable version of GnuTLS. The attacker would perform a SSL man-in-the-middle attack when the victim tries to connect to a server and would present a specially crafted certificate that is not signed by a trusted certificate authority, but claims to be. The certificate should erroneously get accepted by the victim, and the attacker will be able to sniff/modify traffic between the victim and the server.
This issue also impacts certificate verification on the server side as well as certificate verification in other contexts (e.g. verifying OCSP responses)
This bug seems to affect all certificate verification in GnuTLS including client/server certificate verification during SSL handshakes as well as clients verifying that OCSP responses are signed using the right certificates. Certificate verification in GnuTLS goes through roughly the following steps:
If the above checks succeed, then the certificate is considered valid. Note that other verification steps like common name verification are performed elsewhere.
The bug is in the code that checks whether the signer’s certificate is actually allowed to sign other certificates. The _gnutls_verify_certificate2 function calls check_if_ca to see if the signer’s certificate contains the CA attribute. The check_if_ca function calls _gnutls_x509_get_signed_data and _gnutls_x509_get_signature, which return negative values if errors occur. For example, if the certificate signature length is not a multiple of 8 bits, _gnutls_x509_get_signature returns the value -43 (GNUTLS_E_CERTIFICATE_ERROR). Now, the actual bug is in how check_if_ca handles this return value:
If a negative value is received, further checks (including signature verification on the certificate) are bypassed, and the ‘goto cleanup’ call is executed. Here’s what the cleanup code looks like:
Note that the negative result will be returned to the caller. The caller (_gnutls_verify_certificate2) contains:
The caller assumes that a return value of zero indicates an error and that non-zero return values mean that everything is okay.
Let’s assume that this routine is verifying a certificate that claims to be signed by a trusted certificate authority (the issuer DN in the certificate matches one of the trusted CAs’ DN). If this certificate contains errors, the check_if_ca function will skip signature verification and return a negative value. The _gnutls_verify_certificate2 function will assume that everything is okay (i.e. that the certificate is indeed signed by a trusted CA). Eventually, certificate verification will succeed, and signature verification will never have been performed.
I’m not familiar with GnuTLS’s support for certificate/key pinning; I have not experimented with the options listed at http://www.gnutls.org/manual/html_node/Certificate-verification.html. So, I cannot comment on that.
Anybody using software that uses GnuTLS is affected. Typically, this will be Linux applications. Both the client side and the server side for SSL connections are affected; however, the server side vulnerability only matters if its clients are being authenticated using certificates.
End users using Linux should update GnuTLS to version 3.2.12. This will not help with applications that are statically linked against an older version of GnuTLS; you will need to update those separately.
If your application uses GnuTLS and is dynamically linked against it, encourage your users to install the latest version of GnuTLS. If your application is statically linked against GnuTLS, you’ll need to push out an application update linked against the latest version of GnuTLS.