We were recently informed about a possible security vulnerability that has
been published as
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
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
How keys are verified
X509Certificate#verify uses OpenSSL’s
function internally, which delegates to
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
in this scenario. Omitting this check has no significant impact on the overall
security of the X.509 trust model.
Section 18.104.22.168 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.
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
In conclusion, we believe that
X509Certificate#verify operates as expected.
Others have independently arrived at the
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
Posted by emboss on 9 May 2014Read more at the source