Рассуждения об уязвимости CVE-2014-2734

Недавно мы были уведомлены о возможной уязвимости, которая опубликована как CVE-2014-2734. Опираясь на детальный анализ представленный ниже, мы считаем, что Ruby не подвержен данной уязвимости.

Эта уязвимость дает возможность атакующему подделывать произвольные корневые сертификаты, изменяя их подпись, подменяя оригинальный приватный ключ сертификата на ключ, выбранный атакующим.

Проверка уязвимости

Ниже представлен наш анализ CVE-2014-2734. Мы смогли сократить оригинальную проверку, что позволяет, как нам кажется, лучше уловить суть проверки:

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

Может показаться удивительным, что X509Certificate#verify возвращает true. Оригинальный сертификат может содержать Subject Public Key Info указывающий на оригинальный публичный ключ, который отличается от публичного ключа для forge_key. Очевидно, что пара публичный/приватный ключ, которая была использована для переподписи сертификата, больше не соотносится с оригинальным публичным ключом, указанным в Subject Public Key Info. Почему же тогда #verify возвращает true?

Как проверяются ключи

X509Certificate#verify использует внутри функцию OpenSSL X509_verify, которая делегирует к ASN1_item_verify. Эти функции устанавливают валидность подписи предоставленным публичным ключом. Но они не проверяют, что предоставленный ключ на самом деле соответствует публичному ключу, указанному в сертификате. Это означает, что возврат true – ожидаемое поведение для X509Certificate#verify в этом сценарии. Пренебрежение этой проверкой не имеет большого влияния на общую безопасность модели доверия X.509.

Секция 4.1.1.3 документа RFC 5280 ясно указывает, что при вычислении подписи сертификата, CA подтверждает корректность информации, содержащейся в сертификате. Так как этот принцип нарушен в коде выше, это не представляет угрозы уязвимости. Сертификат, подделаный или модифицированный таким образом, не может быть применен, пока кто-либо не имеет возможности заставить вас явно довериться сертификату, нарушающему данный принцип.

Потенциальные риски

Рассмотрим два случая:

Переподпись корневого сертификата

Как пользователи, мы доверяем корневым сертификатам безоговорочно. Даже если они не содержат достоверной информации, сам по себе статус узнаваемого публичного корневого сертификата будет говорить о его достоверности. Они являются преднастроенными значениями в хранилищах доверенной информации наших браузеров и операционных систем. Владение ими устанавливает их статус как символ доверия. Например, OpenSSL сам по себе не проверяет подписи само-подписанных корневых сертификатов по-умолчанию по тем же самым причинам, см. X509_V_FLAG_CHECK_SS_SIGNATURE documentation.

Переподписанный корневой сертификат становится де-факто “само-подписанным” (хотя и с недостоверной Subject Public Key Info). Это не на много более опасно, чем само-подписанный корневой сертификат. На самом деле, каждый может сделать свои само-подписанные сертификаты, которые могут почти полностью совпадать с достоверным корневым сертификатом – кроме подписи. Пока мы доверяем сертификату только по принадлежности, такой самозваный сертификат будет бессмысленен без активного клиентского согласия на доверие.

Переподпись промежуточного или листового сертификата

Переподпись некорневого сертификата также не влияет на безопасность модели доверия X.509. Пока мы заранее не обладаем сертификатами такого типа, их подделка будет выявлена во время процедуры валидации пути. Таким образом, подпись любого некорневого сертификата проверяется с использованием публичного ключа запрашиваемого сертификата. В некоторой точке цепи сертификатов подделка будет в конечном счете обнаружена по недостоверной подписи сертификата.

Заключение

Мы считаем, что X509Certificate#verify работает как ожидается. Другие независимо пришли к тому же заключению, и поэтому мы обсудили CVE-2014-2734, и запросили ее отмену. Вы можете прочесть наш полный анализ оригинальной проверки уязвимости включая комментарии.