Аспекты стойкости протокола TLS, являющегося одним из повсеместно используемых для защиты информации в сетях, обсуждаются не только в рамках классических моделей безопасности протоколов (см. статьи 1, 2 и 3 нашего блога), но и в контексте обеспечения защиты данных в протоколах более высокого уровня, которые зачастую используют TLS довольно нетипичными (и, полагаем, не рассматривавшимися изначально разработчиками протокола SSL/TLS) способами. В 2009 году была обнаружена уязвимость при использовании TLS одним из таких способов. Данной уязвимости, ставшей причиной введения в RFC 5746 расширения Renegotiation Indication, и посвящена данная статья.
Несколько слов о протоколе TLS
Для принципиального понимания рассматриваемой атаки необходимо иметь достаточно общее представление о протоколе TLS. В протоколе можно выделить две основные фазы: фазу согласования параметров и ключей (handshake, в русскоязычной литературе часто используется представляющийся нам спорным в качестве термина прямой перевод «рукопожатие») и фазу передачи данных. Вся информация по завершению фазы согласования передается под защитой согласованных ключей – вплоть до согласования новых, возможного в рамках процесса, называемого renegotiation («пересогласование»). Важно отметить, что порядок обмена сообщениями для согласования новых параметров и ключей в процессе renegotiation, вообще говоря, отличается от исходного согласования только тем, что происходит в зашифрованном виде.
«Безобидная» особенность протокола TLS
У нарушителя, имеющего возможность читать и модифицировать канал связи между клиентом и сервером, есть одна интересная и с первого взгляда совсем безобидная возможность. Идейно – возможность провести renegotiation вместо первичного согласования: для этого ему требуется установить исходное соединение с сервером с односторонней аутентификацией (на рисунке сообщения, передаваемые под защитой данного соединения обозначены синим), а затем устроить renegotiation для клиента-жертвы, перешифровывая сообщения клиента на ключах, выработанных между нарушителем и сервером (после установления нового соединения между клиентом и сервером – на рисунке обозначено красным – нарушитель заканчивает свои действия).
Заметим, что коды аутентификации сообщений, вычисляемые в конце в сообщении Finished, не могут помешать нарушителю осуществить задуманное, поскольку они считаются по исходному открытому тексту сообщений согласования.
Зачем это нарушителю?
Казалось бы, что эта возможность дает нарушителю? Да, он останется незамеченным и для клиента (который вовсе не заметит никаких изменений), и для сервера (для которого общение с клиентом будет выглядеть как предваренное согласованием с односторонней аутентификацией и последующим renegotiation), но возможностей как читать, так и модифицировать пересылаемые от клиента (равно как и от сервера) сообщения у него будет не больше, чем обычно – ведь без действий нарушителя общение клиента с сервером и так начиналось бы по общедоступному открытому каналу связи.
Однако при этом нарушитель имеет возможность эксплуатировать последствия неоправданной уверенности опирающихся на TLS протоколов в том, что сообщения, переданные по туннелю после аутентификации, являются столь же доверенными, сколь и переданные по туннелю, в котором позже была проведена аутентификация (подробно данный аспект защищенности протоколов рассматривался, например, в этой работе). Таким образом, у нарушителя появляется возможность добавить произвольное сообщение перед настоящими сообщениями клиента и заполучить у сервера полное доверие к этим сообщениям.
Банки, деньги, TLS
Рассмотрим пример, иллюстрирующий реальность угрозы, которая следует из наличия у нарушителя описанной возможности.
Предположим, пользователь заходит в браузере на сайт банка www.bank.com, который поддерживает защищенное соединение по https. Будем предполагать, что некоторое время назад пользователь уже заходил на этот сайт и авторизовывался, а значит, в его запросе будет присутствовать заголовок Cookie и сервер не запросит его ввести логин и пароль снова.
Злоумышленник перехватывает сообщения от пользователя и сохраняет их, не перенаправляя на сервер банка. Затем злоумышленник устанавливает защищенное соединение с сервером банка и в рамках этого соединения отправляет свой незаконченный HTTP-запрос (без пустой строки в конце). Сервер банка сохраняет этот запрос и ожидает его завершения.
Далее злоумышленник инициирует renegotiation и перенаправляет сохраненные сообщения пользователя на сервер банка. После окончания renegotiation HTTP-запрос пользователя доходит до сервера, где он «склеивается» с отправленным ранее запросом злоумышленника. Результатом этого «склеивания» является корректный HTTP-запрос с действием, которое необходимо злоумышленнику, и заголовками пользователя (в том числе и заголовком Cookie). Таким образом, сервер выполнит запрос злоумышленника, считая его пользователем.
Как себя обезопасить
Метод решения данной проблемы непосредственно на уровне протокола TLS описан в RFC 5746. Он состоит в определении расширения Renegotiation Indication, связывающего каждое новое повторное согласование соединения с предшествующими сообщениями Finished, что препятствует внедрению сообщений противника в цепочку сообщений между клиентом и сервером.
Опишем этот механизм подробнее. Чтобы обеспечить защищенный renegotiation, клиент и сервер добавляют в сообщения client hello и server hello (которые посылаются и при установлении сеанса, и при начале renegotiation) специальное поле renegotiation_info. При исходном соединении это поле должно быть пустым, а при renegotiation в это поле помещается контрольная информация о предыдущем соединении (client_verify_data и server_verify_data). Стоит отметить, что сообщение client hello, используемое при создании соединения, может вместо пустого поля renegotiation_info содержать специальный идентификатор алгоритма TLS_EMPTY_RENEGOTIATION_INFO_SCSV.
Обе стороны, получив соответствующие сообщения, проверяют присутствие в них поля renegotiation_info, а также корректность значения этого поля. Если все проверки прошли успешно, то соединение продолжается. Если же какая-либо сторона обнаруживает несоответствие (например, сервер считает, что происходит renegotiation, а в клиентском приветствии поле renegotiation_info оказалось пустым), то соединение разрывается. Любое изменение указанного поля со стороны нарушителя будет обнаружено одной из сторон с помощью штатного механизма протокола TLS – при проверке кода аутентификации, присутствующего в сообщении Finished.
Далее представлена схема установления соединения с поддержкой renegotiation_info.
Схема защищенного renegotiation:
Данное расширение поддерживается всеми актуальными версиями КриптоПро CSP – поддержка сервером данного расширения, а также наличие требования его поддержки у клиента настраивается в контрольной панели КриптоПро CSP.
Скачать скрипт, иллюстрирующий базовый сценарий описанной атаки.
Станислав Смышляев, к.ф.-м.н.,
начальник отдела защиты информации
ООО "КРИПТО-ПРО"
Евгений Алексеев, к.ф.-м.н.,
инженер-аналитик 1 категории
ООО "КРИПТО-ПРО"
Антон Прохоров,
инженер-аналитик 2 категории
ООО "КРИПТО-ПРО"