HTTP – механизмы аутентификации

Hmac (код авторизации сообщений на основе хэша)

HMAC расшифровывается как Hash-based message authorization code – код авторизации сообщений на основе хэша и является более строгим типом аутентификации, более распространенным в финансовых API. В HMAC только отправитель, и получатель знают секретный ключ, который больше неизвестен никому.

Затем сообщение кодируется секретным ключом и проходит через алгоритм безопасного хеширования (SHA – secure hashing algorithm). (Хеш – это зашифрованная строка на основе алгоритма.) Результирующее значение, называемое сигнатурой, помещается в заголовок запроса.

Сервер API (получатель), получая запрос, принимает те же системные свойства (отметка времени запроса плюс идентификатор учетной записи) и использует секретный ключ (который известен только запрашивающей стороне и серверу API) и SHA для генерации одной и той же строки. Если строка соответствует подписи в заголовке запроса, запрос принимается. Если строки не совпадают, запрос отклоняется.

Вот диаграмма, отображающая процесс авторизации HMAC:

Важным моментом является то, что секретный ключ (критический для восстановления хэша) известен только отправителю и получателю. Секретный ключ не включается в запрос. Безопасность HMAC используется, когда нужно убедиться, что запрос является подлинным и не может быть подделан.

Немного воды или, что же автор хотел всем этим сказать?

В преамбуле к статье я писал, что занимаюсь дурью проектирую протокол беспарольной аутентификации в Web, который бы сильно облегчил всем нам (конечным пользователям сайтов) жизнь, избавляя от парольного ада. И эта статья написана, чтобы  «раскрывать причины технических решений, закладываемых в новый протокол». Так вот, касаемо схемы авторизации, я делаю ставку на SRP.

На самом деле протоколов авторизации гораздо больше, чем было описано выше. Но SRP – это, на мой взгляд, самая крутая схема, созданная профильным специалистом, выпускником Стэндфордского университета (Thomas Wu), и проверенная его коллегами и другими специалистами по безопасности.

Похожее:  Что означает ошибка на сайте госуслуги и методы ее исправления

Возникает закономерный вопрос? Если эта схема такая крутая и древняя, почему она не получила до сих пор широкого распространения.

Я думаю, что этот протокол просто опередил свое время. Тогда аутентификацию предполагалось выполнять на клиенте в браузере. А javascript находился в зачаточном состоянии и мог, в лучшем случае вывести алертом «hello word». А нужна была арифметика на больших числах. Сейчас уже есть, но время упущено.

И самое главное, веб сообщество до сих пор не осознало, что процесс аутентификации необходимо выносить за рамки прямого взаимодействия сервер–браузер (равно как и аутентификацию в иных системах). В самом деле, ведь никто в здравом уме не хотел бы реализовывать вручную TLS  (на javascipt/PHP/JAVA)?

И если это осознать, то не трудно видеть, что гораздо более правильным решением, поступить также с аутентификацией: создать протокол более низкого уровня, заточить его на использование парольных менеджеров (как сейчас менеджеры сертификатов и криптопровайдеры).

Что документируется в разделе аутентификации

В документации API не нужно подробно объяснять внешним пользователям, как работает аутентификация. Отсутствие объяснений внутренних процессов аутентификации, является лучшей практикой, поскольку хакерам будет сложнее злоупотреблять API.

Тем не менее нужно объяснить необходимую информацию:

  • как получить API ключ;
  • как пройти аутентификацию запроса;
  • сообщения об ошибках, связанных с неверной аутентификацией;
  • чувствительность информации аутентификации;
  • период действия токена доступа (авторизации).

Если есть открытый и закрытый ключи, нужно объяснить, где следует использовать каждый ключ, и отметить, что закрытые ключи не должны использоваться совместно. Если разные уровни лицензий предоставляют разный доступ к вызовам API, эти уровни лицензирования должны быть явно указаны в разделе авторизации или в другом месте.

Поскольку раздел API ключей важен, и нужен разработчикам до того, как они начнут использовать API, этот раздел должен быть в начале руководства.

Хешируем

Ну хорошо. Попробуем усилить элементарную схему. Первое, что приходит на ум: будем передавать не пароль P, а его хэш H. И сервер будет хранить не исходный пароль, а его хеш. Теперь исходный пароль пользователей не сможет узнать ни MitM, ни взломщик БД.

Для надежности, возьмём в качестве хеширующей функции SHA2 или SHA3. 256-битов на текущий момент вполне достаточно. Но если хотите – обе функции поддерживают режим 512 бит. Хотя признаться, такое количество бит потребует сделать в БД поле размером в 64 байта!

Хорошо. Вот только злоумышленнику MitM не нужно уже знать пароль – ему достаточно узнать его хэш. Мало того, если пользователь использует такой же пароль на другом сайте, и тот сайт использует подобную “защиту”, то MitM и там может “поживиться” (ему уже не обязательно взламывать канал, достаточно зайти “легально”).

Базовая схема аутентификации (Basic Authentication Scheme)

«Базовая» схема аутентификации (Basic Authentication Scheme) основана на модели, согласно которой клиент должен аутентифицировать себя с помощью идентификатора пользователя и пароля для каждой области. Значение области следует считать непрозрачной строкой, которую можно сравнить только на равенство с другими областями на этом сервере.

Для “Basic” вышеупомянутая структура используется следующим образом:

challenge = “Basic” realmcredentials = “Basic” basic-credentials

После получения неавторизованного запроса на URI в пределах пространства защиты сервер источника МОЖЕТ ответить на запрос, подобный следующему:

WWW-Authenticate: Basic realm=”WallyWorld”

где «WallyWorld» – это строка, назначенная сервером для идентификации защитного пространства “Request-URI”. Прокси может ответить тем же вызовом, используя поле заголовка “Proxy-Authenticate”.

Scrypt’им

В принципе, описанная выше схема уже надежна в некоторой степени. И уж более надежна чем предыдущие. Но тут есть одна засада.

Производительность компьютеров растет. И хотя закон Мура давно как не действует (по слухам, с 2006 года), и рост уже не экспоненциальный, на “плато” мы ещё не вышли. То что ранее считалось невозможным, теперь доступно многим. Например, аренда на время вычислительных кластеров с фантастической мощностью.

поговаривают, что

количество хешей, которое обсчитывается в сети Bitcoin каждые три секунды, достаточно, чтобы найти коллизию для SHA-1. Источник.

Теперь взломщик БД может попытаться восстановить пароли интересующих его учетных записей, даже если они захешированы с солью (все восстанавливать нет смысла и не хватит времени).

Как? В начале по таблице известных паролей: синтетических qwerty, популярных 123 и когда-то угнанных реальных. Затем, путём тупого перебора символов из заданного алфавита. Алгоритм концептуально прост: берем пароль-кандидат, вычисляем hash( password, salt ), сравниваем результат. Соль учетной записи известна, ибо хранится рядом с хешем пароля.

На нашу беду, процесс перебора хорошо параллелится. А значит, в теории рост производительности не ограничен (правда только в теории; практика – вещь куда более суровая).

Вот для примера расчеты

Этой проблемой озадачились уже достаточно давно. И в результате усилий криптографов, на свет появилась такая функция как scrypt.

Функция scrypt делает почти тоже самое, что и хэш-функция (на самом деле использует в качестве базы SHA2-256), но создана таким образом, чтобы усложнить атаку перебором при помощи ПЛИС: FPGA, ASIC и подобных. Она заставляет использовать в алгоритме много циклов и ветвлений (чего суперскаллярные процессоры крайне не любят), к тому же, требует слишком много памяти на одно ядро.

Поэтому, вместо стандартной хеширующей функции, мы будем использовать scrypt. WebCryptApi пока её не поддерживает, но для javascript-разработчиков есть уже реализованные библиотеки. В остальном схема взаимодействия пока остается прежней. И вроде бы, надежной.

Но защитит ли она от пассивного MitM? Нет. Ибо мы всё ещё посылаем на сервер всегда один и тот же хеш. А значит, перехватив передачу итогового хеша на сервер, злоумышленник может в последствии легально его использовать для входа под чужой учеткой.

1.4. Ограничения

Схема дайджест-аутентификации (Digest authentication scheme), описанная в этом документе, страдает многими известными ограничениями. Она предназначена для замены обычной аутентификации и ничего более. Это система, основанная на пароле, и (на стороне сервера) страдает от всех тех же проблем, что и любая система паролей.

Пользователи и разработчики должны знать, что этот протокол не так безопасен, как “Kerberos”, и не так безопасен, как любая схема закрытого ключа на стороне клиента. Тем не менее, это лучше, чем ничего, лучше, чем то, что обычно используется с “telnet” и “ftp”, и лучше, чем обычная аутентификация “Basic”.

Дайджест схема аутентификации доступа концептуально аналогична базовой схеме. Форматы измененной строки заголовка “WWW-Authenticate” и строки заголовка “Authorization” указаны ниже. Кроме того, указывается новый заголовок “Authentication-Info”.

Если сервер получает запрос на объект, защищенный от доступа, и приемлемый заголовок авторизации не отправляется, сервер отвечает кодом состояния “401 неавторизован” и заголовком “WWW-Authenticate” в соответствии с определенной выше структурой, которая для Схемы дайджеста используется следующим образом:

challenge = “Digest” digest-challenge

digest-challenge = 1#( realm | [ domain ] | nonce | [ opaque ] |[ stale ] | [ algorithm ] | [ qop-options ] | [auth-param] )

domain = “domain” “=” <“> URI ( 1*SP URI ) <“>URI = absoluteURI | abs_pathnonce = “nonce” “=” nonce-valuenonce-value = quoted-stringopaque = “opaque” “=” quoted-stringstale = “stale” “=” ( “true” | “false” )algorithm = “algorithm” “=” ( “MD5” | “MD5-sess” | token )qop-options = “qop” “=” <“> 1#qop-value <“>qop-value = “auth” | “auth-int” | token

Смыслы значений директив заголовка ответа “WWW-Authenticate”, использованных выше, следующие:

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

10. Атаки по предварительно вычисленным словарям

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

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

Противодействие этой атаке заключается в том, чтобы клиенты были настроены так, чтобы требовать использования необязательной директивы «cnonce».

11. Групповые атаки методом грубой силы

С помощью дайджест-аутентификации MITM может выполнять выбранную атаку с открытым текстом и может собирать ответы от многих пользователей на один и тот же одноразовый номер. Затем он может найти все пароли в любом подмножестве пространства паролей, которое сгенерирует одну из пар “nonce/response” за один проход по этому пространству.

Это также сокращает время нахождения первого пароля на коэффициент, равный количеству собранных пар “nonce/response”. Такой поиск пространства паролей часто можно выполнять параллельно на многих машинах, и даже одна машина может очень быстро искать большие подмножества пространства паролей – существуют отчеты о поиске всех паролей с шестью или менее буквами в течение нескольких часов.

Противодействие этой атаке заключается в том, чтобы клиенты были настроены так, чтобы требовать использования необязательной директивы «cnonce».

12. Подмена поддельных серверов

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

Этот тип атаки более сложен при использовании дайджест-аутентификации, но клиент должен знать, что требуется использовать дайджест-аутентификацию, возможно, с использованием некоторых из методов, описанных выше, для противодействия атакам типа «человек посередине».

13. Хранение паролей

Дайджест-аутентификация требует, чтобы агент аутентификации (обычно сервер) сохранял некоторые данные, полученные из имени пользователя и пароля, в «файле паролей», связанном с данной областью. Обычно это может содержать пары, состоящие из имени пользователя и H (A1), где H (A1) – это усвоенное значение имени пользователя, области и пароля, как описано выше.

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

С другой стороны, для получения пароля пользователя потребуется расшифровка или, что более вероятно, атака методом перебора. Это причина того, что область является частью переваренных данных, хранящихся в файле паролей. Это означает, что если один файл пароля аутентификации Digest скомпрометирован, он автоматически не скомпрометирует других с тем же именем пользователя и паролем (хотя он подвергает их атаке методом грубой силы “brute force”).

Это имеет два важных последствия для безопасности. Во-первых, файл паролей должен быть защищен, как если бы он содержал незашифрованные пароли, потому что для обеспечения доступа к документам в его области он эффективно защищает.

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

14. Резюме

По современным криптографическим стандартам дайджест-аутентификация слаба. Но для широкого спектра целей он полезен в качестве замены базовой аутентификации. Это исправляет некоторые, но не все, недостатки базовой аутентификации. Его сила может варьироваться в зависимости от реализации.

В частности, структура одноразового номера (которая зависит от реализации сервера) может повлиять на простоту установки атаки воспроизведения. Целый ряд серверных опций является подходящим, поскольку, например, некоторые реализации могут быть готовы принять серверные накладные расходы одноразовых “nonce” или дайджестов, чтобы исключить возможность воспроизведения.

Суть в том, что * любая * совместимая реализация будет относительно слабой по криптографическим стандартам, но * любая * совместимая реализация будет намного превосходить базовую аутентификацию.

2. Аутентификация клиентов с использованием дайджест-аутентификации

Дайджест-аутентификация не обеспечивает надежного механизма аутентификации, например, по сравнению с механизмами на основе открытого ключа. Однако он значительно сильнее, чем (например) CRAM-MD5, который был предложен для использования с LDAP [10], POP и IMAP (см. RFC 2195 [9]). Он призван заменить гораздо более слабый и еще более опасный базовый механизм.

Digest Authentication не обеспечивает никакой защиты конфиденциальности, кроме защиты действительного пароля. Все остальные запросы и ответы доступны перехватчику.

Дайджест-аутентификация обеспечивает только ограниченную защиту целостности сообщений в любом направлении. Если используется механизм “qop=auth-int”, то те части сообщения, которые использовались при расчете значений директивы ответа в поле заголовка WWWAuthenticate и Authorization (см. Раздел 3.2 выше), защищены. Большинство полей заголовка и их значения могут быть изменены как часть атаки «человек посередине». (man-in-the-middle)

3. Ограниченные использование значений Nonce

Digest схема использует одноразовый номер (nonce), указанный сервером, чтобы инициировать генерацию значения дайджеста запроса (как указано в разделе 3.2.2.1 выше). Как показано в примере одноразового номера в разделе 3.2.1, сервер может создать одноразовый номер таким образом, чтобы его можно было использовать только от конкретного клиента, для конкретного ресурса, в течение ограниченного периода времени или количества использований или любого другого ограничения.

Это усиливает защиту, например, от атак воспроизведения (replay attacks) (см. 4.5). Однако следует отметить, что метод, выбранный для генерации и проверки одноразового номера, также влияет на производительность и ресурсы. Например, сервер может разрешить использование каждого одноразового значения только один раз, ведя запись о том, был ли возвращен каждый недавно выданный одноразовый номер и отправляя директиву “next-nonce” в поле заголовка “Authentication-Info” каждого ответа.

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

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

4. Сравнение дайджеста с базовой аутентификацией

И дайджест, и базовая аутентификация находятся на слабом конце спектра безопасности. Но сравнение между этими двумя пунктами указывает на полезность и даже необходимость замены Basic на Digest.

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

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

5. Повторные атаки

Атака воспроизведения против дайджест-аутентификации обычно была бы бессмысленной для простого запроса GET, поскольку перехватчик уже видел бы единственный документ, который он мог получить с помощью воспроизведения. Это связано с тем, что URI запрошенного документа переваривается в запросе клиента, и сервер доставит только этот документ.

Таким образом, для некоторых целей необходимо защитить от повторных атак. Хорошая реализация дайджеста может сделать это различными способами. Созданное сервером значение «nonce» зависит от реализации, но если оно содержит дайджест IP-адреса клиента, метку времени, ETag ресурса и частный ключ сервера (private server key) (как рекомендовано выше), то атака воспроизведения не является простой.

Злоумышленник должен убедить сервер в том, что запрос поступает с ложного IP-адреса, и заставить сервер доставить документ на IP-адрес, отличный от адреса, на который, по его мнению, он отправляет документ. Атака может быть успешной только в период до истечения времени.

Для приложений, в которых нельзя допустить возможность повторной атаки, сервер может использовать одноразовые значения nonce, которые не будут учитываться при повторном использовании. Это требует от сервера дополнительных затрат на запоминание того, какие значения nonce использовались до тех пор, пока не истечет временная метка nonce (и, следовательно, созданный с ее помощью дайджест), но это эффективно защищает от атак воспроизведения.

Реализация должна уделять особое внимание возможности повторных атак с запросами POST и PUT. Если сервер не использует одноразовые или иным образом ограниченные одноразовые номера и / или не настаивает на использовании защиты целостности “qop=auth-int”, злоумышленник может воспроизвести действительные учетные данные из успешного запроса с поддельными данными формы или другим телом сообщения.

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

8. Человек посередине

Как базовая, так и дайджест-проверка подлинности уязвимы для атак «человек посередине» (MITM), например, со стороны враждебного или скомпрометированного прокси-сервера. Ясно, что это представляет все проблемы подслушивания. Но это также предлагает некоторые дополнительные возможности для атакующего.

Возможная атака «человек посередине» будет заключаться в добавлении слабой схемы аутентификации к набору вариантов выбора в надежде, что клиент будет использовать схему, которая предоставляет учетные данные пользователя (например, пароль). По этой причине клиент должен всегда использовать самую сильную схему, которую он понимает из предложенных вариантов.

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

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

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

Обоюдный challenge

Казалось бы где тут подвох? Да почти нигде. Вот только, что если наш злоумышленник MitM вклинится в момент аутентификации и поменяет challenge от сервера на более простой (например – все нулевые биты, или вообще пустой)? Зачем? А чтобы попытаться облегчить себе задачу обратного восстановления H из Hs.

Защититься от такой потенциальной атаки можно, если клиент будет генерировать свой challenge и использовать его для хеширования пароля. Теперь на шаге 2, клиент вычисляет Hs = hash(H,server-challenge,client-challenge) и отправляет Hs вместе со своей версией challenge.

А Схема защиты на симметричных ключах

Пусть H – это тот самый хеш клиента, по которому сервер его аутентифицирует. H хранится на сервере. H может быть потенциально стать доступным взломщику БД.

Пусть клиент имеет некий ключ K, которым он зашифровывает свой исходный аутентификационный хеш H: V = EK(H), где E – функция шифрования на ключе K. Итоговый шифр V вместе с H сервер хранит в своей БД. Если алгоритм шифра выбран надежный, то из пары (V, H) восстановить исходный ключ почти невозможно.

Теперь в процессе аутентификации нам остается передать защищенным образом пару (H, V) серверу. Тот сверит H, расшифрует V и убедится, что мы действительно знаем ключ К, а не украли H при взломе БД. 

Это был концепт. Теперь конкретика. 

Определим функцию hmac как функцию HMAC-SHA2-256. Salt и challenge должны быть равны длине блока хеширующей функции. В нашем случае – 256 бит. Определим функцию E – как функцию шифрования, а функцию D – как функцию расшифровывания на базе симметричного шифра AES-256.  Наконец, определим функцию scrypt, как функцию, возвращающую 256-битный хеш от пароля и его соли.

На стороне клиента производятся предварительные вычисления:

  1. Защитим исходный пароль пользователя, вычислив H_p=scrypt(password,salt).

  2. Сформируем аутентификационный хеш H=hmac_{H_p}(login).

  3. Сформируем код подтверждения .

  4. Сформируем шифр аутентификационного хеша V = E_K (H).

При регистрации клиент посылает серверу пару (H, V) в открытом виде. Заметим, что сервер не знает ни исходный пароль пользователя, ни его первичный хеш Hp.

Алгоритм авторизации клиента теперь такой:

Api ключ

Большинство API требуют авторизации ключом API, чтобы использовать API. Ключ API представляет собой длинную строку, которую обычно включают либо в URL запроса, либо в заголовок запроса. Ключ API в основном служит способом идентификации лица, выполняющего запрос API (аутентифицируя для использования API). Ключ API также может быть связан с конкретным приложением, которое регистрируется.

Ключи APK используют строку в свойстве заголовка для авторизации запросов

API могут дать как открытый, так и закрытый ключ. Открытый ключ обычно включается в запрос, в то время как закрытый ключ рассматривается скорее как пароль и используется только при обмене данными между серверами. На некоторых сайтах документации API, при заходе на сайт, ключ API автоматически заполняется в примере кода и API Explorer.

Domain – домен

Цитированный разделенный пробелами список URI, как указано в RFC XURI [7], которые определяют пространство защиты (protection space). Если URI является “abs_path”, он относится к каноническому корневому URL (см. Раздел 1.2 выше) сервера, к которому осуществляется доступ.

Абсолютный URI (absoluteURI) в этом списке может относиться к серверу, отличному от того, к которому осуществляется доступ. Клиент может использовать этот список, чтобы определить набор URI, для которых может быть отправлена одна и та же информация аутентификации:

любой URI, который имеет URI в этом списке в качестве префикса (после того, как оба были сделаны абсолютными), можно считать находящимся в одном и том же защитном пространстве. Если эта директива (domain) опущена или ее значение пусто, клиент должен предположить, что пространство защиты состоит из всех URI на отвечающем сервере.

“nonce” – это указанная сервером строка данных, которая должна генерироваться уникальным образом каждый раз при получении ответа 401. Рекомендуется, чтобы строкой nonce были base64 или шестнадцатеричные данные. В частности, поскольку строка nonce передается в строках заголовка в виде строки в кавычках, символ двойной кавычки не допускается.

Содержимое одноразового номера зависит от реализации. Качество реализации зависит от удачного выбора. Одноразовый номер может, например, быть сконструирован как кодировка base 64

time-stamp H(time-stamp “:” ETag “:” private-key)

Message-qop

Директива “message-qop” указывает параметры «качества защиты» (“quality of protection”), применяемые к ответу сервера. Значение «auth» указывает на аутентификацию; значение «auth-int» указывает на аутентификацию с защитой целостности. Сервер ДОЛЖЕН использовать в ответе то же значение для директивы “message-qop”, которое было отправлено клиентом в соответствующем запросе.

Необязательный дайджест ответа в директиве “response-auth” поддерживает взаимную аутентификацию – сервер подтверждает, что знает секрет пользователя, и с помощью (qop=auth-int) также обеспечивает ограниченную защиту целостности ответа. Значение “response-digest” рассчитывается так же, как и для “request-digest” в заголовке авторизации, за исключением того, что если “qop=auth” или не указано в заголовке авторизации для запроса, A2

A2 = “:” digest-uri-value

и если “qop=auth-int”, то A2

A2 = “:” digest-uri-value “:” H(entity-body)

где “digest-uri-value” – это значение директивы “uri” в заголовке авторизации в запросе. “Cnonce-value” и “nc-value” ДОЛЖНЫ быть теми для запроса клиента, на который это сообщение является ответом. Директивы «response-auth», «cnonce» и «nonce-count» ДОЛЖНЫ БЫТЬ присутствовать, если указано “qop=auth” или “qop=auth-int”.

Nextnonce

Значение директивы “nextnonce” – это тот раз, когда сервер желает, чтобы клиент использовал его для будущего ответа аутентификации. Сервер может отправить заголовок Authentication-Info с полем nextnonce в качестве средства реализации одноразовых или иным образом изменяющихся одноразовых номеров (nonces).

Если поле nextnonce присутствует, клиент ДОЛЖЕН использовать его при создании заголовка Authorization для своего следующего запроса. Невыполнение этого требования клиентом может привести к запросу на повторную аутентификацию с сервера с помощью «stale=TRUE».

Реализации сервера должны тщательно учитывать последствия использования этого механизма для производительности; конвейерные запросы будут невозможны, если каждый ответ содержит директиву nextnonce, которая должна использоваться при следующем запросе, полученном сервером.

Следует учитывать компромиссы между производительностью и безопасностью, позволяя использовать старое одноразовое значение в течение ограниченного времени, чтобы разрешить конвейеризацию запросов. Использование одноразового номера (nonce-count) может сохранить большинство преимуществ безопасности нового одноразового номера сервера без вредного влияния на конвейерную обработку.

Ложка дёгтя в бочке мёда.

Есть одна проблема – математическая. Эллиптические кривые используются в криптографии относительно недавно и ещё слабо изучены. Даже сами математики говорят, что теория эллиптических кривых только развивается. Не случайно, что самые крупные достижения в математике последних лет (теорема о модулярности эллиптических кривых, приведшая к доказательству известного Диафантова уравнения,  [всё ещё спорное] доказательство ABC-гипотезы) тесно связаны с эллиптическими кривыми.

Известно также, что существуют классы эллиптических кривых, которые являются слабыми. Однако на сегодняшний день не известно методик, которые бы однозначно могли оценить надёжность кривых. А вот методики, которые позволяют генерировать слабые кривые, замаскированные под сильные, есть.

Обнадёживает тут только то, что даже если эллиптическая кривая «подведёт», пароль пользователя всё ещё находится под надёжной защитой благодаря scrypt и hmac.

Последствия нехватки безопасности api

Почему даже API-интерфейсы нуждаются в аутентификации? Для API, которые предназначены только для чтения, иногда пользователям не нужны ключи. Но большинство коммерческих API требуют авторизации в виде ключей API или других методов. Если нет никакой защиты API, пользователи могут совершать неограниченное количество запросов API без какой-либо регистрации. Разрешение неограниченных запросов усложнит модель дохода для вашего API.

Вдобавок, без аутентификации не было бы простого способа связать запросы с конкретными данными пользователя. И не было бы способа защиты от запросов от злонамеренных пользователей, которые могут удалить данные другого пользователя (например, путем удаления запросов DELETE для учетной записи другого пользователя).

Наконец, не получится отследить, кто использует API или какие конечные точки используются чаще всего. Очевидно, что разработчики API должны подумать о способах аутентификации и авторизации запросов к своим API.

В целом, аутентификация и авторизация с помощью API служат следующим целям:

Схема на базе протокола srp

SRP — протокол парольной аутентификации, устойчивый к прослушиванию и MITM-атаке и не требующий третьей доверенной стороны. Имеет свой RFC2945. Есть производные от него стандарты для протоколов Telnet, TLS. Единственный из представленных, который проводит окончательную взаимную авторизацию обеих сторон. Хорошо описан как в Википедии, так и на Хабре пользователем @datacompboy.

Тем не менее, для генерации секретного ключа x протокол использует устаревшие подходы: (уже  не криптостойкую) функцию SHA-1 и  простую схему хеширования: x = hash(salt | hash(login | ‘:’ | pass). В свете современных тенденций к взлому паролей брутфорсом офлайн на специализированных ПЛИС или арендованных кластерах, данный подход должен быть улучшен, использованием scrypt.

Для реализации схемы нам понадобятся: большое простое число N, генератор g мультипликативной группы Z*N и параметр k = hash(N, g). В качестве g и N стороны используют числа, определенные в RFC-5054. Так, например, g = 2, а «мультипликативная группа» – это просто степени двойки; точнее их остатки по модулю N.

Процесс регистрации пользователя в системе:

  1. Клиент отправляет серверу свой login и свою 256-битную версию соли saltC.

  2. Сервер генерирует свою 256-битную версию соли saltS для пользователя login.

  3. Клиент формирует общую 256-битную соль: salt = saltC ^ saltS.

  4. Клиент вычисляет секретный 256-битный ключ x = scrypt(password, salt) от своего пароля

  5. Клиент вычисляет верификатор пароля V = gx (mod N).

  6. Клиент посылает на сервер пару (saltC, V).

  7. Сервер вычисляет общую соль salt аналогично клиенту в п. 3.

  8. Сервер хранит учетные данные пользователя в форме: login, salt, V.

Процесс авторизации пользователя в системе:

  1. Клиент формирует случайное 256-битное число a и вычисляет 2048-битное A = ga (mod N).

  2. Клиент делает запрос на сервер со своим login, и числом А.

  3. Сервер формирует случайное 256-битное число b и вычисляет 2048-битное B = (kv gb) (mod N).

  4. Сервер посылает клиенту пару (salt, B).

  5. Обе стороны вычисляют u = hash(A | B). В оригинальном RFC указано, что параметр u – 32-битное беззнаковое, получаемое от результата примененной хеш-функции hash(A | B).

  6. Пользователь вычисляет свой ключ x на основе пароля и соли, аналогично пп. 4 процесса регистрации.

  7. Пользователь вычисляет сессионный ключ K следующим образом: S = (B – kgx)a ux (mod N); K = hash(S).

  8. Сервер вычисляет сессионный ключ K следующим образом: S = (Avu)b (mod N); K = hash(S).

  9. Пользователь вычисляет M1 = hash( hash(N) ^ hash(g) | hash(login) | salt | A | B | K ) и отправляет на сервер.

  10. Сервер дождавшись от пользователя M1, проверяет его, производя аналогичные п. 9 вычисления.

  11. Сервер вычисляет M2 = hash( A | M1 | K ) и отправляет клиенту.

  12. Клиент проверяет M2 сервера. На этом этапе аутентификация считается завершенной.

В функции hash операция | означает конкатенацию аргументов. Если предполагается, что ключ K не будет использоваться в дальнейшем взаимодействии (например, для шифрования или аутентификации пакетов), то пп. 9-12 к исполнению обязательны. А если будет, то проверка излишняя, т.к. несогласованный ключ не позволит проводить корректное взаимодействие. Но я бы всё-таки оставил эти пункты обязательными.

Согласно спецификации, пользователь должен прервать аутентификацию, если получил B = 0 (mod N) или u = 0. (Полагаю, что B не должно быть также равно –kV, т.к. в этом случае клиент получит S = 0a ux (mod N) = 0).

Сервер должен прервать аутентификацию, если получил A = 0 (mod N). Клиент должен первым доказать, что получил тот же ключ K. Если клиенту это не удалось, сервер должен прервать аутентификацию, без своего доказательства K.

Требования к аутентификации и шифрованию

Следует периодически проверять всю информацию, доступную на публичном web-сервере, и определять необходимые требования безопасности. При выполнении этого организация должна идентифицировать информацию, которая имеет одни и те же требования безопасности и защиты.

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

Часть пятая: проверка силы пароля

Во-первых, вам нужно прочитать эту маленькую статью, чтобы узнать реальное положение вещей: 500 самых распространённых паролей (на англ.)

Ладно, быть может это и не самый каноничный лист самых распространённых паролей во всех системах везде за всё время, но он хорошо демонстрирует нам то, как безосновательно пользователи подходят к выбору пароля, если к ним не предъявлены требования. Плюс, этот лист до боли похож на лист паролей, полученных в результате анализа недавно украденных аккаунтов.

Итак: без требований к минимальной длине пароля, 2% пользователей используют один из топ-20 самых популярных паролей. Вывод: если у хакера будет словарь из всего лишь 20 паролей, каждый 50-ый аккаунт на вашем веб-сайте будет взломан.

Избежать этого можно установив на сайте минимальный порог энтропии пароля. Специальная публикация национального института стандартов и технологий содержит набор очень хороших предложений. Так, скомбинировав словарь и анализ раскладки клавиатуры, можно отбросить 99% всех ненадёжных паролей на уровне 18-ти битной энтропии.

Рекомендуем посмотреть данный комикс, чтобы отбросить стереотип о трудной запоминаемости паролей с высокой энтропией.

Часть третья: использование секретных вопросов

Не используйте “секретные вопросы”. “Секретные вопросы” — антипаттерн безопасности. Ознакомьтесь с документом по четвёртой ссылки из раздела ОБЯЗАТЕЛЬНО ДЛЯ ПРОЧТЕНИЯ. Вы можете спросить Сару Пэйлин о том случае, когда её почтовый ящик на Yahoo! был взломан во время прошлой предвыборной кампании, потому что её секретный ответ был “Wasilla High School”!

Даже если пользователи сами вводят секретный вопрос, велика вероятность, что они выберут:

  • Вопрос из “стандартного набора”, как девичье имя матери или имя любимого питомца
  • Простая информация, которую может раздобыть любой желающий из их личного блога, профиля LinkedIn или тому подобного
  • Любой вопрос, ответ на который получить перебором легче, чем подобрать пароль. А именно: любой вопрос, который вы только можете вообразить.

Вывод: секретные вопросы по существу не безопасны в фактически всех своих формах и проявлениях и не должны быть применены для аутентификации по любой причине.

Настоящая причина, почему секретные вопросы вообще существуют в том, что они так удобно экономят деньги на звонках в тех. поддержку с просьбой выслать код реактивации. Это цена безопасности и репутации Сары Пэйлин. Стоит того? Уверен, что нет.

Часть шестая: все больше и больше – или предотвращение скоропалительных попыток входа

Для начала давайте ознакомимся с цифрами

Если нет времени на ознакомление с данными статьи, вот краткая информация:

  1. Практически моментально можно взломать слабый пароль, даже если взламываете его при помощи счёт
  2. Практически моментально можно взломать буквенно-цифровой 9-ти символьный пароль, если он не чувствителен к регистру знаков
  3. Практически моментально можно взломать сложный символьно-буквенно-цифровой, верхне- и нижнерегистровый, если в его составе менее 8-ми символов (обычный компьютер может подобрать пароль, состоящий из 7 символов за считанные дни или даже часы)
  4. Однако придется потратить уйму времени, чтобы взломать даже шестизначный пароль, если у вас стоит ограничение на одну попытку в секунду

Так что же мы уяснили из этих цифр? Ладно, много, но выделим главное: не так уж сложно защититься от быстрых бесконечных попыток войти в систему (так называемых брут-форс). Но все не так просто, как кажется.

Короче говоря, есть три варианта эффективной защиты от брут-форса (и атаки по словарю, но учитывая, что вы уже используете политику сильных паролей, это больше не проблема):

Лучшая практика №1: короткие промежутки времени, увеличивающиеся с ростом числа неудачных попыток входа, например:

  • 1 неудачная попытка – нет задержки
  • 2 неудачные попытки – 4 секунды
  • 3 неудачные попытки – 8 секунд
  • 4 неудачные попытки – 16 секунд
  • и так далее

Для DoS атаки такая система очень неудобна, так как каждый последующий промежуток времени блокировки больше всех предыдущих вместе взятых.

Уточняем. Задержка – это не задержка перед возвратом ответа браузера.
Это больше похоже на таймаут или рефактерный период, в течение которого
попытки войти в какой-либо аккаунт или с определенного IP- адреса
вовсе не принимаются. То есть правильные credentials или как их там,
не вернутся я так понимаю после успешного входа в систему. и неверные
кредентиалы не увеличат задержку.

Лучшая практика №2: среднесрочная задержка, которая наступает после N неудачных попыток, например:

  • 1-4 неудачные попытки – нет задержки
  • 5 попыток – 15-30 минут задержка

Для DoS взломать эту схему сложно, но, безусловно, выполнимо. Также стоит отметить, что такая задержка раздражает авторизованных пользователей. особо забывчивые вас возненавидят.

Лучшая практика №3: совмещение этих двух подходов, либо фиксированное короткое время задержки, наступающее после N числа неудачных попыток, например:
1-4 неудачных попытки – нет задержки
5 – 20 секунд задержки
или увеличение времени задержки с ростом числа неудачных попыток входа, например:

  • 1 неудачная попытка – 5 секунд
  • 2 неудачные попытки – 15 секунд
  • 3 неудачные попытки – 45 секунд

Эта последняя схема была заимствована из списка лучших предложений OWASP (ссылка 1 из списка “ОБЯЗАТЕЛЬНО ДЛЯ ПРОЧТЕНИЯ”) и должна рассматриваться как лучшая практика.

По правилу большого пальца, я бы сказал, что чем надежнее ваш пароль,
тем меньше вам придётся мучить пользователей задержками. Если вы требуете
надежный (с учетом регистра символов требование наличия букв и цифр)
9 символов в пароле, можно предоставить пользователям 2-4 попытки
ввода пароля до включения блокировки.

👨‍💻 практическое занятие: авторизация

В своем найденном опен-сорс проекте найдем информацию об авторизации для запросов к API. Ответьте на следующие вопросы:

  • Какого рода авторизация требуется для отправки запросов к API?
  • Существуют ли разные уровни доступа в рамках авторизации (например, платные и бесплатные), которые определяют, сколько запросов можно сделать или какие типы информации можно получить?
  • Можно ли вы получить ключ API или какой-либо другой метод авторизации, необходимый для выполнения тестовых вызовов API?
  • Как информация об авторизации интегрируется в раздел “Начало работы”?

Go next ➡

Подведём итоги

Параметр / Схема

1. Симметричная на базе HASH

2. На базе ECDSA

3. SRP-6a

Скорость

Проверка на сервере реализуется быстрее

Проверка подписи на стороне сервера в 2 раза медленнее клиента

Медленная, требует длинной арифметики и 4 пакета для завершения аутентификации

Технические сложности

Отсутствуют; может быть реализована на нативном js; работает достаточно быстро.

Отсутствует поддержка произвольной кривой в WebCryptoApi на клиенте

Уже никаких

Потенциальные уязвимости

Уязвима к компрометации БД и последующему контролю канала сервера; уязвима в процессе регистрации пользователя

Существуют классы уязвимых эллиптических кривых. Методики оценки безопасности кривых ещё не разработано. Вероятность, что выбрана «слабая» кривая, всегда остается.

Задача решения дискретного логарифма может быть решена теоретически; надежность базируется на сложности факторизации N; числа N, g, k известны всем.

Обратить особое внимание на

Случайное число k, генерируемое клиентом в процессе подписи, не должно использоваться дважды!

Числа A, B не должны быть равны 0 и 0, –vk соответственно.

Защита от пассивного MitM

да (но только не в момент регистрации)

да

да

Защита от активного MitM

да (только, если учетные данные не компрометированы)

да

да

Защита пароля при компрометации БД

да

да

да

Защита после компрометации БД и прослушивании канала

нет

да

да

Препятствие «легальному» доступу злоумышленника после компрометации БД

да

да

да

Взаимная аутентификация сторон

нет

нет

да

Защита от фишинга (попытка злоумышленника выдать себя за легальный сервер)

нет

нет

да

Требует наличие какого-либо доп. защищенного канала при регистрации клиента?

да

нет

нет

Защита слабых паролей в момент авторизации

нет

да

да

Защита от владельцев ЦОД

нет

нет

нет

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *