Pull to refresh

Первая работающая атака на SSL/TLS-протокол

Reading time8 min
Views57K
Передаваемые по SSL-соединению данные можно расшифровать! Для этого Джулиану Риццо и Тай Дуонгу удалось использовать недоработки в самом протоколе SSL. И пусть речь пока не идет о полной дешифровке трафика, разработанная ими утилита BEAST может извлечь из зашифрованного потока то, что представляет собой наибольший интерес, — секретные кукисы с идентификатором сессии пользователя.



Что такое BEAST?


Всего 103 секунды потребовалось утилите BEAST (Browser Exploit Against SSL/TLS), чтобы расшифровать секретную кукису для входа в аккаунт PayPal. Посмотреть видеокаст можно на Youtube. Это не фейк. Живая демонстрация утилиты прошла в рамках конференции Ekoparty в Буэнос-Айросе, где исследователи выступили с докладом и показали работающий proof-of-concept. Используемая уязвимость действительно позволяет незаметно перехватывать данные, передаваемые между веб-сервером и браузером пользователя. По иронии судьбы атака эксплуатирует не какую-то новую найденную в протоколе брешь, а уязвимость SSL/TLS десятилетней давности, долгое время считавшуюся чисто теоретической. Но, как говорится, раз в год и палка стреляет, так что уж за десять лет уязвимость точно может перейти из разряда теоретических во вполне себе практическую.

Исследователи пока не публикуют утилиту, но делятся whitepaper'ом о проделанной работе. Программа состоит из двух элементов: снифера, который анализирует HTTPS-трафик, и специального агента, написанного на JavaScript и Java, который должен быть подгружен в браузере жертвы (для этого, к примеру, необходимо заставить пользователя открыть страницу с нужным кодом). Агент нужен для того, чтобы особым образом внедрять данные в тот же безопасный канал связи, который используется для передачи секретных кукисов. Как это позволяет дешифровать данные? Вот здесь вступает давно известная уязвимость SSL 3.0/TLS 1.0, на которой мы остановимся подробнее.


Проблема режима простой замены



Особенности шифрования SSL 1.0


Протокол SSL 1.0/TLS 3.0 позволяет использовать шифрование симметричным ключом, используя либо блочные, либо потоковые шифры. На практике, однако, обычно используется блочные шифры, и описываемая нами атака применима именно для них. Чтобы вникнуть в суть, нужно хорошо представлять себе базовые понятия.

Принцип работы блочного шифра заключается в отображении блоков открытого текста в зашифрованные блоки того же размера. Проще всего представить блочный шифр в виде гигантской таблицы, содержащей 2^128 записей, каждая из которых содержит блок текста М и соответствующий ему зашифрованный блок С. Соответственно, для каждого ключа шифрования будет отдельная такая таблица. Далее мы будем обозначать шифрование в виде функции:

C = E(Key, M), где M — исходные данные, Key — ключ шифрования, а C — полученные зашифрованные данные.

Блоки имеют небольшой размер (как правило, 16 байт). Поэтому возникает вопрос: как зашифровать длинное сообщение? Можно разбить сообщение на блоки одинаковой длины (те же самые 16 байт) и зашифровать каждый блок в отдельности. Такой подход называется режимом простой замены (ECB, Electronic codebook), но используется редко. На то есть причина: если мы будем шифровать два одинаковых по содержимому блока, то в результате и на выходе получим два одинаковых зашифрованных блока. Это влечет за собой проблему сохранения статистических особенностей исходного текста, которая хорошо продемонстрирована на иллюстрации. Для избегания такого эффекта был разработан режим сцепления блоков шифротекста (СВС, Cipher-block chaining), в котором каждый следующий блок открытого текста XOR'ится с предыдущим результатом шифрования:

Ci = E(Key, Mi xor Ci-1)

Во время шифрования первого блока исходный текст XOR’ится некоторым вектором инициализации (Initialization Vector, IV), который заменяет результат предыдущего шифрования, которого по понятной причине нет. Как видишь, все довольно просто. Однако эта теория описывает ситуацию для одного большого объекта, такого, например, как файл, который легко разбивается на блоки. В свою очередь, SSL/TLS является криптографическим протоколом — ему необходимо шифровать не отдельный файл, а серию пакетов. SSL/TLS-соединение может быть использовано для отправки серии HTTPS-запросов, каждый из которых может быть разбит на один или более пакетов, которые, в свою очередь, могут быть отправлены в течение как нескольких секунд, так и нескольких минут. В данной ситуации есть два способа использовать режим CBC:

  1. обрабатывать каждое сообщение как отдельный объект, генерировать новый вектор инициализации и шифровать по описанной схеме.
  2. обрабатывать все сообщения как будто они объединены в один большой объект, сохраняя CBC-режим между ними. Этого можно достичь, используя в качестве вектора инициализации для сообщения n последний блок шифрования предыдущего сообщения (n-1).

Внимание, важный момент. Протокол SSL 3.0/TLS 1.0 использует второй вариант, и именно в этом кроется возможность для проведения атаки.


Принцип действия CBC-шифра



Предсказуемый вектор инициализации


Атака строится на нескольких допущениях, но опыт создателей BEAST показал, что их вполне реально реализовать в реальной жизни. Первое допущение: злоумышленник должен иметь возможность снифать трафик, который передает браузер. Второе допущение: плохой парень каким-то образом должен заставить жертву передавать данные по тому же самому безопасному каналу связи. Зачем это нужно? Рассмотрим случай, когда между компьютерами Боба и Элис установлено безопасное соединение. К нам попадает сообщение, i-блок которого, как мы предполагаем, содержит, пароль Элис (или секретную кукису — неважно). Обозначим зашифрованный блок как Ci, соответственно Mi — ее пароль. Напомню, что Ci = E (Key, Mi xor Ci-1). Теперь предположим, что ее пароль — это Р. Главная идея в том, что мы можем проверить правильность нашего предположения!

Итак, мы знаем (так как смогли перехватить) вектор инициализации, который будет использоваться для шифрования первого блока следующего сообщения. Это, соответственно, последний блок предыдущего сообщения (в зашифрованном виде) — обозначим его IV. Мы также перехватили и знаем значение блока, идущего перед Ci — обозначим его Ci-1. Эти данные нам очень нужны. С их помощью мы особым образом формируем сообщение так, чтобы первый блок был равен следующему:

M1 = Ci-1 xor IV xor P

Если сообщение удалось передать по тому же защищенному каналу связи, то первый блок нового сообщения после шифрования будет выглядеть следующим образом:

C1 = E(Key, M1 xor IV) =
= E(Key, (Ci-1 xor IV xor P) xor IV)
= E(Key, (Ci-1 xor P))
= Сi


Все, что я сделал, — это использовал полную форму записи M1, после чего упростил формулу, используя тот факт, что (IV xor IV) уничтожится (замечательное свойство XOR'а). Получается, что если наше предположение относительно пароля Элис верное (то есть M действительно равен P), то первый зашифрованный блок нового сообщения C1 будет равен ранее перехваченному Ci! И наоборот: если предположение неверное, равенства не будет. Так мы можем проверять наши предположения.


Передача запроса на сервер для реализации атаки на SSL



Особенности перебора


Если предположить, что у нас есть кучу времени и множество попыток, мы можем повторять эту технику вновь и вновь, пока не найдем верное значение M. Однако на практике блок M — 16 байтов в длину. Даже если мы знаем значение всех байт кроме двух, на то, чтобы отгадать оставшиеся байты, нам понадобится 2^15 (32 768) попыток. А если мы не знаем вообще ничего? Короче говоря, техника может сработать лишь в единственном случае — если у тебя есть некоторое ограниченное количество предположений относительно значения M. Еще точнее: мы должны знать большую часть содержимого этого блока — это единственный способ использовать описанную уязвимость. Тут есть одна хитрость.
Предположим, что злоумышленник может контролировать, каким образом данные будут располагаться в шифруемом блоке. Вернемся опять к примеру с Элис. Допустим, мы знаем, что длина ее пароля — 8 символов. Если злоумышленник может расположить пароль таким образом, чтобы в первый блок попал только один символ, а оставшиеся семь попали в следующий. Идея в том, чтобы передать в первых 15 байтах первого блока заведомо известные данные — тогда можно будет подобрать только последний байт, являющийся первым символом пароля. Например, допустим, что нужно отправить строку вида: «user: alice password: ********», где "********" — непосредственно сам пароль. Если злоумышленнику удастся передать строку так, чтобы она была разбита на следующие блоки "[lice password: *] [*******.........]", то подбор первого символа пароля уже не кажется невыполнимой задачей. Напротив, в худшем случае нам понадобится жалкие 256 попыток. А в случае особой удачи и вовсе одна :)! Подобрав первый байт, можно сдвинуть границу разбиения на один символ: то есть передавать в первом сообщении 14 заранее известных байт. Блок теперь будет заканчиваться двумя первыми байтами пароля, первый из которых мы уже подобрали. И опять: получаем 256 необходимых попыток для того, чтобы угадать второй его байт. Процесс можно повторять до тех пор, пока пароль не будет подобран. Этот принцип используется и в BEAST для подбора секретной кукисы, а в качестве известных данных используются модифицированные заголовки запроса. Подбор ускоряется за счет сужения возможных символов (в запросе можно использовать далеко не все), а также за счет предположений имени кукисы.


Всего 103 секунды потребовалось для расшифровки секретной кукисы PayPal



Реализация атаки


Впрочем, сама уязвимость и оптимизированный способ для выполнения дешифрования описаны уже давно. Что действительно удалось разработчикам BEAST, так это реализовать все необходимые условия для выполнения атаки:
  1. атакующий должен иметь возможность прослушивать сетевые соединения, инициированные браузером жертвы;
  2. у атакующего должна быть возможность внедрить агент в браузер жертвы;
  3. агент должен иметь возможность отправлять произвольные (более-менее) HTTPS-запросы;
В самом начале материала я уже говорил, что важной частью BEAST является так называемый агент, который сможет передавать нужные злоумышленнику запросы на сервер (по защищенному протоколу). Исследователи составили список различных технологий и браузерных плагинов, который могут выполнить это условие. Как оказалось, их довольно много: Javascript XMLHttpRequest API, HTML5 WebSocket API, Flash URLRequest API, Java Applet URLConnection API, и Silverlight WebClient API. Однако в первом приближении некоторые из них оказались непригодны из-за наличия ограничений, препятствующих реализации атак. В результате остались только HTML5 WebSocket API, Java URLConnection API, и Silverlight WebClient API. В момент, когда исследователи сообщили о своем баге вендорам, у них на руках был работающий агент на базе HTML5 WebSockets. Но технология эта постоянно развивается, а сам протокол постоянно меняется. В результате работающий агент банально перестал работать. Текущая версия BEAST, которую парни представили общественности, состоит из агента, написанного на Javascript/Java, и сетевого снифера.
Незаметно внедрить апплет или JavaScript пользователю на самом деле не является такой уж сложной задачей. Но остается небольшой нюанс — для того, чтобы скрипт или апплет могли отправлять данные по установленному жертвой соединению, необходимо обойти еще и ограничения SOP (same-origin policy, правило ограничения домена). Это важная концепция безопасности для некоторых языков программирования на стороне клиента, таких как JavaScript. Политика разрешает сценариям, находящимся на страницах одного сайта, доступ к методам и свойствам друг друга без ограничений, но предотвращает доступ к большинству методов и свойств для страниц на разных сайтах. Проще говоря, запущенный на одной странице клиент не сможет делать запросы к нужному сайту (скажем, Paypal.com). Чтобы обойти политику SOP, авторы нашли в виртуальной машине Java 0day-уязвимость и написали для нее работающий сплоит. Только не думай, что это позволяет читать существующие кукисы. Если бы это было так, тогда зачем нужен был весь этот сыр-бор с зашифрованным трафиком? Используя сплоит для обхода SOP, можно отправлять запросы и читать ответы сервера (в том числе ответы с новыми кукисами), но нельзя считывать существующие кукисы, которые сохранены в браузере. Разработчики делятся целой историей о создании агента в своем блоге.

Respect


В заключение хочется отметить огромный труд исследователей, которые не только сумели использовать уязвимость, забытую всеми десять лет назад, но также приложили много труда для того, чтобы заставить свою утилиту работать. В рамках этого материала мы довольно сильно упростили описания используемых техник, пытаясь передать основную идею. Но мы получили истинное удовольствие от прочтения детального документа от исследователей, в которых они в деталях рассказывают о реализованной атаке. Good job!


Масштабы проблемы


Итак, каковы же масштабы бедствия? Или иными словами — кто уязвим? Практически любой сайт, использующий TLS1.0, который является наиболее распространенным протоколом безопасности. Забавно, что после всей этой шумихи с BEAST, многие стали проявлять интерес к более новым версиям протокола — TLS 1.1 и выше. Но многие ли сайты уже сейчас поддерживают эти протоколы? Да практически никто! Посмотри на иллюстрацию. Даже несмотря на то, что TLS 1.1 уже пять лет, его используют единицы!



Другой вопрос: как обезопасить себя? На самом деле, паниковать нет смысла — уязвимость уже исправлена в большинстве браузеров. Но если паранойя берет верх, можешь попробовать отключить небезопасные протоколы в браузере (TLS 1.0 и SSL 3.0), а заодно и Java. Правда, не стоит в этом случае сильно удивляться, что многие сайты перестанут работать.


image
Журнал Хакер, Ноябрь (11) 154
Коллективный разум
.

Подпишись на «Хакер»
Tags:
Hubs:
Total votes 84: ↑77 and ↓7+70
Comments22

Articles

Information

Website
xakep.ru
Registered
Founded
Employees
51–100 employees
Location
Россия