Недавно я писал о недостаточной защите локально сохранённых паролей в Firefox. Как правильно отметили некоторые читатели, злоумышленник с физическим доступом к вашему устройству — не главная угроза. Поэтому взглянем, как разработчики браузеров защищают ваши пароли при их передаче в облако. И Chrome, и Firefox предоставляют сервис синхронизации, который может загружать не только сохранённые пароли, но и куки, и историю просмотров страниц. Насколько безопасен этот сервис?
TL;DR: в настоящее время ответ «нет». У обеих служб есть слабые места в защите. Впрочем, некоторые из этих недостатков хуже других.
Синхронизация Chrome
Начну с синхронизации Chrome, где ответ более предсказуем. В конце концов, несколько вещей указывают на то, что данная услуга создана скорее для удобства, чем для приватности. Например, пароль для защиты ваших данных от Google необязателен. В настройках нет предупреждения типа «Эй, вас не волнует, что мы можем заглянуть в ваши данные? Лучше установите пароль». Вместо этого пользователь должен сам проявить инициативу. Другой признак — то, что Google открывает доступ к паролям через веб-страницу. Вероятно, идея в том, чтобы вы могли открыть эту веб-страницу с чужого компьютера, например, из интернет-кафе. Хорошая идея? Вряд ли.
В любом случае, что произойдет после установки пароля? Он будет использоваться для получения (среди прочего) ключа шифрования — и ваши данные зашифруются этим ключом. Конечно, здесь возникает большой вопрос: если кто-то получит ваши зашифрованные данные с сервера, насколько пароль защищён от брутфорса? Оказывается, Chrome использует PBKDF2-HMAC-SHA1 с 1003 итерациями.
Чтобы это значит? Тут я опять для справки приведу цифры из этой статьи: с учётом этих итераций одна графическая карта Nvidia GTX 1080 может обсчитать 3,2 миллиона хэшей PBKDF2-HMAC-SHA1 в секунду. Это 3,2 миллиона угаданных паролей в секунду. То есть 1,5 миллиарда паролей, известных из различных утечек веб-сайтов, обсчитываются менее чем за 8 минут. Что насчёт надёжного пароля с энтропией 40 бит, который эти специалисты считают средним паролем у людей? Вероятно, специалисты переоценивает возможности людей по выбору хороших паролей, но примерно за два дня этот пароль будет подобран.
На самом деле ситуация ещё хуже. Соль, которую Chrome использует для получения ключа, представляет собой константу. Это означает, что один и тот же пароль у разных пользователей Chrome соответствует одинаковым ключам шифрования. В свою очередь, это значит, что при наличии большого объёма данных от разных пользователей можно проводить атаку сразу на всех. Таким образом, за четыре дня будет подобран пароль к любой учётной записи, где используется пароль с энтропией до 40 бит. Имейте в виду, что у самой Google достаточно оборудования, чтобы проделать эту работу за несколько минут, если не секунд. Я говорю о тех злоумышленниках, кто не хочет тратить на оборудование более 1000 долларов.
Я зарегистрировал этот баг в трекере с номером 820976, следите за обновлениями.
Примечание. Особая благодарность Chrome за креативность в бесполезной трате ресурсов CPU. Эта функция прогоняет PBKDF2 четыре раза, хотя одного прохода достаточно. Первый запуск получает соль от имени хоста и имени пользователя (в случае синхронизации Chrome это константы). Это довольно бессмысленно: соль не должна быть секретом, она просто должна быть уникальной. Так что объединение значений или прогон на них SHA-256 дают тот же эффект. Следующие три запуска генерируют три разных ключа из идентичных входных данных, используя разное число итераций. Один вызов PBKDF2 с генерацией данных для всех трёх ключей явно был бы эффективнее.
Синхронизация Firefox
Синхронизация Firefox использует хорошо документированный протокол Firefox Accounts для установки ключей шифрования. Хотя различные параметры и выполняемые там операции могут запутать, но похоже, что это хорошо продуманный подход. Если кто-то получит доступ к данным, хранящимся на сервере, то им придётся иметь дело с ключами на основе scrypt. Перебор scrypt на специализированном оборудовании гораздо сложнее, чем PBKDF2 хотя бы потому, что каждый вызов scrypt требует 64 МБ памяти — если учитывать параметры, которые использует Mozilla.
Тем не менее, есть существенный недостаток: scrypt работает на сервере Firefox Accounts, а не на стороне клиента. На стороне клиента этот протокол использует PBKDF2-HMAC-SHA256 только с 1000 итерациями. И хотя полученный парольный хэш не хранится на сервере, но если кто-то перехватит его во время передачи на сервер, то сможет относительно легко подобрать пароль. В данном случае одна видеокарта Nvidia GTX 1080 будет проверять 1,2 миллиона хэшей в секунду. Хотя для каждого аккаунта придётся начинать операцию заново, но проверка 1,5 миллиарда известных паролей займёт 20 минут. И пароль с 40-битной энтропией угадают в среднем за пять дней. В зависимости от содержимого учётной записи такая трата ресурсов может окупиться.
Самое интересное: Mozilla оплатила аудит безопасности Firefox Accounts, и этот аудит указал генерацию ключа на стороне клиента как ключевой недостаток. Таким образом, Mozilla знает о проблеме, как минимум, 18 месяцев, а 8 месяцев назад даже опубликовала эту информацию. В чём же дело? Судя по всему, проблему не посчитали слишком важной. Возможно, это отчасти связано с тем, что аудитор неправильно оценил риск:
Атака предполагает очень сильного злоумышленника, который способен обойти TLS.
Конечно, одним из возможных способов проведения атаки стало бы получение валидного сертификата для api.accounts.firefox.com и перенаправление трафика на собственный сервер. Но более вероятно, что будет скомпрометирована безопасность самого сервера api.accounts.firefox.com. Даже если сервер не взломан, всегда есть шанс, что сотрудник Mozilla или Amazon (сервер размещается на AWS) решит взглянуть на чьи-то данные. А что если американские власти постучатся к Mozilla?
Я изначально зарепортил этот баг как 1444866. Сейчас он помечен как дубликат бага 1320222 — я не смог его найти, потому что он был помечен как «важный в отношении безопасности» (security sensitive), хотя не содержит никакой новой информации.
Автор: m1rko