КриптоПро TLS против оракулов Воденея

Публикация: 30 Декабрь 2011 - 16:28, редакция: 26.08.2014 14:35

В продолжение темы уязвимостей в протоколах SSL/TLS рассмотрим ещё одну интересную атаку, связанную с особенностями применения блочных шифров и способами дополнения данных для выравнивания границ блоков.

История данной атаки началась в 2001-м году с выступления профессора Швейцарской высшей технической школы Сержа Воденея (Serge Vaudenay) на конференции CRYPTO 2001 (на Rump Session). На EUROCRYPT 2002 была представлена полная версия работы Воденея, где описывается атака на блочный шифр, работающий в режиме сцепления блоков шифртекста (CBC) при использовании заполнения PKCS#5. Активный нарушитель, который прослушивает канал связи и может вставлять сообщения, путём анализа ответов об ошибках на свои модифицированные сообщения может восстановить открытый текст, соответствующий переданному ранее сообщению. В дополнение к самому описанию метода криптоанализа, Воденей описывает возможности применения данного метода к реально используемым протоколам — как SSL/TLS, так и IPSEC, WTLS и SSH2. При этом сама идея построения аналогичных атак с выбором шифртекста на протоколы, использующие определённые режимы шифрования и виды заполнения, возникла ещё раньше у Блейхенбахера (Bleichenbacher).

Атака Воденея: уязвимость шифрования со сцеплением блоков шифртекста при определенных видах заполнения

Напомним, что для выравнивания сообщения с помощью заполнения PKCS#5 при использовании с блочным шифром с длиной блока b байт (b ≤ 255) сообщение M дополняется s = b − (len(M) mod b) байтами, значение каждого из которых равно s.

Предположим, что у нарушителя есть доступ к некоторому оракулу OK, которому на вход подается пара из синхропосылки C0 и шифртекста C, и который возвращает TRUE в том и только в том случае, когда при расшифровании в режиме сцепления блоков шифртекста получается корректное заполнение PKCS#5. Пусть нарушитель знает шифртекст C = (C1|C2|...|Cm) = EK(M1|M2|...|Mm) (используются обозначения из предыдущей статьи). Для частичного дешифрования блока Ci проводятся следующие действия:

  • Случайным образом выбирается блок (Ci−1)1, для j = 2, 3, ... выбирается порядка 28 блоков (Ci−1)j, отличающихся от (Ci−1)1 и друг от друга в последнем байте.
  • Для каждого из (Ci−1)j, j = 1, 2, ..., на вход оракулу подается строка C'j = ((Ci−1)j|Ci). При некотором j' для (Ci−1)j' оракул возвращает TRUE, т.к. при переборе всех возможных значений последнего байта (Ci−1)j при расшифровании в блоке P = (Ci−1)j ⊕ DK(Ci) обязательно встретится корректное заполнение PKCS#5 из одного байта со значением 1. Такой исход является наиболее вероятным, но возможны и попадания в корректное заполнение большей длины. В любом случае, при получении ответа TRUE, (Ci−1)* полагается равным (Ci−1)j'.
  • Для нахождения длины подобранного корректного заполнения PKCS#5 перебираются сообщения
    (Ci−1)*(1) = (Ci−1)* ⊕ (00|00| . . . |00|01),
    (Ci−1)*(2) = (Ci−1)* ⊕ (00| . . . |00|01|00),
    ...,
    (Ci−1)*(b) = (Ci−1)* ⊕ (01|00| . . . |00|00)
    и на вход оракулу OK подаются строки (C(j)|Ci), j = b, b − 1, ..., 1. В случае если ответ FALSE впервые появится от оракула при j = j* , становится известно, что в сообщении, получаемом расшифрованием на ключе K из шифртекста (C0|C1|...|Ci−2|(Ci−1)*|Ci ) в конце стоит j* байт со значением j*.
  • Поскольку (xx|xx|...|j*|j*|...|j*) = (Ci−1)* ⊕ DK(Ci) (здесь xx - неизвестные байты), и Mi = Ci−1 ⊕ DK(Ci), то Mi = Ci−1 ⊕ (Ci−1)* ⊕ (xx|xx|...|j*|j*|...|j*), и из этого выражения можно вычислить последние j* байт блока Mi.

Зная последние j* байт блока Mi, можно аналогичным образом подобрать шифртекст с корректным заполнением длиной j* + 1 и вычислить ещё один байт Mi. Таким образом можно восстановить весь открытый текст.

Аналогичной атаке подвержены и другие виды заполнения для выравнивания границ блоков.

Атака Воденея в случае протокола TLS, или Не сотвори себе оракула

Предположим, активный нарушитель имеет доступ к каналу связи, защищённому протоколом TLS, и может как читать пакеты в канале, так и посылать произвольные пакеты в сторону сервера TLS. Для реализации описанной выше атаки нарушителю  требуется после отправки каждого пакета с модифицированным шифртекстом получать информацию о том, прошла ли проверка корректности заполнения для выравнивания границ блоков открытого текста.

На практике получение такой информации затруднено, т.к. при обнаружении некорректного заполнения сервер TLS отправляет зашифрованное сообщение об ошибке и прерывает сессию TLS. Даже если нарушитель может отличить сообщение о некорректном заполнении от ошибки проверки целостности пакета (например, по журналу сервера TLS), следующая сессия TLS будет использовать другой ключ шифрования и дальнейшие обращения к такому оракулу невозможны. Воденей называет такого оракула "заминированным", т.к. он "взрывается" при получении первого сообщения с некорректным заполнением. Тем не менее, с помощью такого оракула можно осуществить проверку гипотезы о равенстве конца открытого текста некоторому значению.

Для защиты от данной атаки в протоколе TLS версии 1.1 исключено отдельное сообщение об ошибке decryption_failed, означавшее в версии 1.0 некорректное заполнение. Таким образом, сервер TLS версии 1.1 не различает ошибки проверки заполнения и проверки целостности пакета — в обоих случаях ошибка будет bad_record_mac.

В другой работе Воденей с соавторами предложили модификацию этой атаки, которая различает ошибки проверки заполнения и проверки целостности пакета путём измерения времени реакции сервера TLS на модифицированный шифртекст. Действительно, имитозащита в протоколе TLS накладывается на открытый текст, а уже после этого применяется заполнение и осуществляется зашифрование. Таким образом, большее время обработки пакета до возврата ошибки означает, что заполнение корректно, а ошибка произошла при проверке целостности.

Авторам удалось провести атаку на практике, подобрав пароль к почтовому ящику на сервере IMAP, который передавался по протоколу TLS. Клиентом выступал Outlook Express 6, который по умолчанию проверяет почту каждые 5 минут. Если в почтовом ящике пользователя есть 5 папок, то при проверке почты пароль передаётся 5  раз, что даёт 60 сессий в час. Outlook Express не обращал внимания на прерывание сессий из-за атаки и "молча" устанавливал новые соединения. Расчёты авторов показали, что для подбора несложного пароля по словарю потребуется в среднем 166 сессий, которые Outlook Express осуществит меньше чем за 3 часа.

Для предотвращения временной атаки в спецификации TLS версии 1.2 указано, что лучшим методом защиты является вычисление значения имитовставки даже в случае некорректного заполнения, например, вычисление значения имитовставки по всему полученному после расшифрования фрагменту, предполагая отсутствие заполнения.

Заметим, что предложенные в TLS версий 1.1 и 1.2 контрмеры могут быть реализованы в сервере, работающем по протоколу TLS версии 1.0, т.е. применение данных контрмер является вопросом реализации сервера и не влияет на совместимость с клиентами, в которых не реализована поддержка TLS новых версий.

Как защититься

Использование данной атаки на практике затруднено и поэтому маловероятно. 

Самым простым способом защиты протокола TLS от данной атаки является отказ от блочных алгоритмов шифрования. Так же как и в случае с атакой Барда-Дэя, рассмотренной в предыдущей статье, рекомендуется использовать набор алгоритмов шифрования TLS_RSA_WITH_RC4_128_SHA. Переход на него, скорее всего, не создаст проблем совместимости.

Наша реализация TLS и все совместимые с ней не являются уязвимыми к данной атаке, поскольку используют шифрование по ГОСТ 28147-89 в режиме гаммирования, т.е. поточный шифр.

Тема уязвимостей протокола TLS получит продолжение в следующих статьях нашего блога. Не забывайте проверять обновления!

Беляев Анатолий
Гилязов Руслан
Леонтьев Сергей
Попов Владимир
Смирнов Павел
Смышляев Станислав