The GnuTLS certificate verification bug allows attackers to intercept SSL traffic. Learn how the vulnerability works and how to mitigate it.
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 nonzero 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:
_gnutls_x509_verify_certificatefunction is called. If the provided certificate itself is trusted, then this function simply returns.
_gnutls_verify_certificate2, which is given the certificate to verify as well as a list of potential signers. For the first check, it is given the complete set of trusted certificate authorities, and for subsequent checks in the certificate chain, it is just given the previous certificate in the chain.
_gnutls_verify_certificate2function verifies that the maximum certificate chain length of 4,096 has not been exceeded, ensures that the given certificate is issued by one of the potential signers provided by
_gnutls_x509_verify_certificate, verifies that the signer’s certificate is actually allowed to sign other certificates, verifies the actual signature on the certificate, verifies that the certificate is currently valid, etc.
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_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 (
The caller assumes that a return value of zero indicates an error and that nonzero return values mean that everything is OK.
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 OK (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’ 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.