---
layout: news_post
title: "Dispute of Vulnerability CVE-2014-2734"
author: "emboss"
translator:
date: 2014-05-09 05:33:54 +0000
tags: security
lang: en
---

We were recently informed about a possible security vulnerability that has
been published as
[CVE-2014-2734](http://cve.mitre.org/cgi-bin/cvename.cgi?name=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:

{% highlight ruby %}
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
{% endhighlight %}

It may come as a surprise that `X509Certificate#verify` returns `true`.
The original certificate may contain a
[Subject Public Key Info](http://tools.ietf.org/html/rfc5280#section-4.1.2.7)
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`](https://github.com/openssl/openssl/blob/master/crypto/x509/x_all.c#L74)
function internally, which delegates to
[`ASN1_item_verify`](https://github.com/openssl/openssl/blob/master/crypto/asn1/a_verify.c#L134).
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](https://www.openssl.org/docs/crypto/X509_VERIFY_PARAM_set_flags.html).

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](http://tools.ietf.org/html/rfc5280#section-6).
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](https://github.com/adrienthebo/cve-2014-2734/)
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](https://gist.github.com/emboss/91696b56cd227c8a0c13)
including comments.
