Dispute of Vulnerability CVE-2014-2734

We were recently informed about a possible security vulnerability that has been published as CVE-2014-2734. However, based on our detailed analysis below, we do not consider Ruby to be vulnerable.

This vulnerability could possibly allow an attacker to forge arbitrary root certificates by modifying the certificate’s signature, effectively replacing the certificate’s original private key with one chosen by the attacker.

Proof of Concept

The following is our analysis of CVE-2014-2734, we were able to reduce the original PoC, which we believe captures the essence of the proof of concept:

require 'openssl'

forge_key = OpenSSL::PKey::RSA.new(2048)
raw_certificate = File.read("arbitrary.cer")
cert = OpenSSL::X509::Certificate.new(raw_certificate)
resigned_cert = cert.sign(spoof, OpenSSL::Digest::SHA1.new)

resigned_cert.verify(key) #=> true

It may come as a surprise that X509Certificate#verify returns true. The original certificate may contain a Subject Public Key Info pointing to the original public key which is different from the public key of forge_key. Clearly, the public / private key pair that was used to re-sign the certificate no longer matches the original public key referenced in the Subject Public Key Info. Why does #verify return true?

How keys are verified

X509Certificate#verify uses OpenSSL’s X509_verify function internally, which delegates to ASN1_item_verify. These functions establish the validity of the signature given the public key that was presented. However, they will not verify if the given key actually matches any subject public key referenced in the certificate. This means that returning true is expected behavior for X509Certificate#verify in this scenario. Omitting this check has no significant impact on the overall security of the X.509 trust model.

Section 4.1.1.3 of RFC 5280 explicitly states that by computing a certificate’s signature, the CA confirms the correctness of the information contained in the certificate. While this principle is violated in the above example code, it poses no threat to security. A certificate forged or modified in this way cannot be exploited unless someone is able to convince you to explicitly trust a certificate that violates this principle.

Potential risks

There are two cases to consider:

Re-signing a root certificate

As users, we trust root certificates unconditionally. Even if they do not contain valid information, the status of being a publicly acknowledged root certificate alone is what keeps them pristine. They are preconfigured values in the trust stores of our browsers or operating systems. Simply possessing them establishes their status as valid trust anchors. For example, OpenSSL itself does not check the signature of self-signed root certificates by default for the same reasons, cf. X509_V_FLAG_CHECK_SS_SIGNATURE documentation.

A re-signed root certificate becomes a de facto “self-signed” certificate (albeit with incorrect Subject Public Key Info). This is not any more dangerous than a normal self-signed root certificate. In fact, anyone can produce self-signed root certificates which may completely match that of a valid root certificate - except for the signature. Since we trust root certificates merely by possession, such an imposter certificate is meaningless without a client’s active consent to trust it.

Re-signing an intermediate or leaf certificate

Also, re-signing a non-root certificate does not violate the security of the X.509 trust model. While we usually do not possess these kinds of certificates in advance, their forgery would be detected during the path validation procedure. Here, any non-root certificate’s signature is verified using the public key of the issuing certificate. At some point in the certificate chain, the forgery would be ultimately detected in the form of an invalid certificate signature value.

Conclusion

In conclusion, we believe that X509Certificate#verify operates as expected. Others have independently arrived at the same conclusion and we have therefore disputed CVE-2014-2734, and asked for its revocation. You can find our complete analysis of the original proof of concept including comments.