Найти тему
Уловка-32

Криптографическая ошибка в JAVA позволяет злоумышленнику легко обойти проверку идентификации

Оглавление
Критическая уязвимость может позволить противникам легко подделывать сертификаты и подписи / Яндекс.Дзен Уловка-32
Критическая уязвимость может позволить противникам легко подделывать сертификаты и подписи / Яндекс.Дзен Уловка-32

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

Организации, использующие новые версии платформы Java от Oracle, на этой неделе проснулись от тревожного сообщения: Критическая уязвимость может позволить противникам легко подделывать сертификаты и подписи TLS, сообщения двухфакторной аутентификации и учетные данные авторизации, создаваемые рядом широко используемых открытых стандартов.

Уязвимость, которую Oracle устранила во вторник, затрагивает реализацию алгоритма цифровой подписи с эллиптическими кривыми в Java версии 15 и выше. ECDSA - это алгоритм, который использует принципы криптографии эллиптической кривой для цифровой аутентификации сообщений. Ключевым преимуществом ECDSA является меньший размер генерируемых ключей по сравнению с RSA или другими криптоалгоритмами, что делает его идеальным для использования в таких стандартах, как 2FA на основе FIDO, Security Assertion Markup Language, OpenID и JSON.

Доктор Кто и экстрасенсорная бумага

Нил Мэдден (Neil Madden), исследователь из компании по безопасности ForgeRock, обнаруживший уязвимость, сравнил ее с пустыми удостоверениями личности, которые регулярно появляются в фантастическом сериале "Доктор Кто". Экстрасенсорная бумага, из которой сделаны эти карточки, заставляет человека, смотрящего на них, видеть то, что хочет представить главный герой.

"Оказалось, что некоторые последние выпуски Java были уязвимы к подобному трюку в реализации широко используемых подписей ECDSA", - пишет Мэдден. "Если вы используете одну из уязвимых версий, то злоумышленник может легко подделать некоторые типы SSL-сертификатов и рукопожатий (что позволяет перехватывать и изменять сообщения), подписанные JWT, утверждения SAML или токены OIDC id, и даже сообщения аутентификации WebAuthn. И все это с использованием цифрового эквивалента чистого листа бумаги".

Серьезность этой ошибки такова, что если пользователь использует подписи ECDSA для любого из этих механизмов безопасности, то злоумышленник может тривиально и полностью обойти их, если на вашем сервере используется любая версия Java 15, 16, 17 или 18 до апрельского 2022 Critical Patch Update (CPU).

"Для контекста, почти все устройства WebAuthn/FIDO в реальном мире (включая Yubikeys) используют подписи ECDSA, а многие провайдеры OIDC используют JWT с подписью ECDSA", - написал Мэдден

Ошибка, отслеживаемая как CVE-2022-21449, имеет рейтинг серьезности 7,5 из 10 возможных, но Мэдден сказал, что, основываясь на своей оценке, он бы оценил серьезность на 10 баллов "из-за широкого спектра воздействия на различные функции в контексте управления доступом".

Если представить самый ужасный сценарий: ошибка может быть использована злоумышленником за пределами уязвимой сети без какой-либо проверки.

Многие эксперты по безопасности считают эту ошибку в алгоритмах криптографии одной из самых серьезных из огромного количества, выявленных уязвимостей в последнее время. Некоторые исследователи дали однозначную оценку ошибке - это "крипто-баг года".

Фактором, который может "подсластить пилюлю", является то, что Java версии 15 и выше пока еще широко не используются. Данные, собранные в феврале и марте 2021 года компанией Snyk, занимающейся вопросами безопасности, показали, что на Java 15, последнюю на тот момент версию, приходилось 12 процентов развертываний.

Специалисты по кибербезопасности считают, что конкретный недостаток реализации ECDSA, затрагивающий только Java 15 и выше и Oracle версии 7, 8 и 11, может быть результатом отдельных криптографических ошибок, исправленных разработчиками ПО в ранних версиях.

a/0 = действительная подпись

Подписи ECDSA основаны на псевдослучайном числе, обычно обозначаемом как K, которое используется для получения двух дополнительных чисел, R и S. Чтобы проверить действительность подписи, сторона должна проверить уравнение, включающее R и S, открытый ключ подписанта и криптографический хэш сообщения. Если обе стороны уравнения равны, подпись действительна.

В статье, опубликованной в среду, компания Sophos, занимающаяся вопросами безопасности, более подробно объяснила этот процесс:

S1. Выберите криптографически обоснованное случайное целое число K от 1 до N-1 включительно.
S2. Вычислите R из K с помощью умножения по эллиптической кривой.
S3. В маловероятном случае, если R равно нулю, вернитесь к шагу 1 и начните все сначала.
S4. Вычислите S из K, R, хэша, который нужно подписать, и закрытого ключа.
S5. В маловероятном случае, если S равно нулю, вернитесь к шагу 1 и начните сначала.

Чтобы процесс работал правильно, ни R, ни S никогда не могут быть нулями. Это потому, что одна сторона уравнения - R, а другая умножается на R и значение из S. Если оба значения равны 0, то проверка переводится как 0 = 0 X (другие значения из закрытого ключа и хэша), что будет верно независимо от дополнительных значений. Это означает, что злоумышленнику достаточно представить пустую подпись, чтобы успешно пройти проверку.

Madden пишет:

Угадайте, какую проверку забыла Java?
Правильно. Реализация в Java проверки подписи ECDSA не проверяла, равны ли R или S нулю, так что вы могли бы создать значение подписи, в котором они оба равны 0 (соответствующим образом закодированные), и Java приняла бы его как действительную подпись для любого сообщения и для любого открытого ключа. Цифровой эквивалент пустого удостоверения личности.

Ниже приведен интерактивный сеанс JShell, созданный Мэдденом, который показывает, как уязвимая реализация принимает пустую подпись за действительную при проверке сообщения и открытого ключа:

| Welcome to JShell -- Version 17.0.1
| For an introduction type: /help intro
jshell>
import java.security.* jshell> var keys = KeyPairGenerator.getInstance("EC").generateKeyPair() keys ==> java.security.KeyPair@626b2d4a
jshell>
var blankSignature = new byte[64] blankSignature ==> byte[64] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... , 0, 0, 0, 0, 0, 0, 0, 0 }
jshell>
var sig = Signature.getInstance("SHA256WithECDSAInP1363Format") sig ==> Signature object: SHA256WithECDSAInP1363Format<not initialized>
jshell>
sig.initVerify(keys.getPublic()) jshell> sig.update("Hello, World".getBytes()) jshell> sig.verify(blankSignature) $8 ==> true
// Oops, that shouldn't have verified...

Организации, использующие любую из затронутых версий Java для проверки подписей, должны уделять первоочередное внимание исправлениям. Также важно следить за рекомендациями от производителей приложений и продуктов, чтобы узнать, не стали ли уязвимыми их продукты. Хотя угроза CVE-2022-21449 ограничивается новыми версиями Java, ее серьезность достаточно высока, чтобы не терять бдительность.