Статьи

Общие сведения об аутентификации доступа к дайджесту HTTP

Digest Access Authentication — это один из методов, который клиент и сервер могут использовать для обмена учетными данными по HTTP. Этот метод использует комбинацию пароля и других битов информации для создания хеша MD5, который затем отправляется на сервер для аутентификации. Отправка хэша позволяет избежать проблем с отправкой пароля в виде открытого текста, что является недостатком базовой аутентификации доступа.

Дайджест-доступ был первоначально определен в RFC 2069 , а дополнительные усовершенствования безопасности были позже добавлены в RFC 2617, который следует считать текущим стандартом, если вы хотите реализовать этот метод самостоятельно. Мы рассмотрим оба в этой статье.

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

Во-первых, давайте рассмотрим базовую аутентификацию доступа. С вашим браузером вы запрашиваете какой-то объект, который требует от вас аутентификации. Если браузер не кэшировал учетные данные, которые вы уже предоставили, вы получите ответ «HTTP 401 Not Authorized», который содержит следующий заголовок:

  WWW-Authenticate: Basic realm = "example.com" 

Затем ожидается, что клиент / браузер ответит соответствующими учетными данными, чтобы получить доступ.

Имя пользователя и пароль соединяются вместе, например, «admin: p @ ssw0rd». Затем эта строка кодируется в Base64. Закодированная строка (YWRtaW46cEBzc3cwcmQ =) используется в заголовке авторизации, который отправляется обратно на сервер.

  Авторизация: Basic YWRtaW46cEBzc3cwcmQ = 

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

Основная проблема здесь заключается в том, что Base64 является схемой передачи данных; это не схема хеширования или шифрования. Это также может быть простой текст. Digest Access Authentication пытается улучшить это, посылая пароль в виде хешированного значения, что намного труднее (не невозможно) восстановить значение открытого текста.

Работа с дайджест-аутентификацией доступа

При работе с Digest Access Authentication именно сервер должен сделать первый шаг, когда обнаружит, что клиент пытается получить доступ к ограниченной области. Есть несколько значений, которые сервер должен предоставить как часть заголовка WWW-Authenticate, который нужен клиенту.

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

В PHP применение md5()

 <?php
$nonce = md5(uniqid());

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

 <?php
$opaque = md5(uniqid());

Последнее значение realm — это просто строка для отображения пользователям, чтобы они знали, какое имя пользователя и пароль они должны предоставить. Он также используется клиентом для генерации хэша для отправки обратно на сервер.

 <?php
$realm = 'Authorized users of example.com';

Все эти значения используются для составления директивы WWW-Authenticate и отправки в качестве ответа клиенту.

 <?php
if (empty($_SERVER['PHP_AUTH_DIGEST']) {
    header('HTTP/1.1 401 Unauthorized');
    header(sprintf('WWW-Authenticate: Digest realm="%s", nonce="%s", opaque="%s"', $realm, $nonce, $opaque));
    header('Content-Type: text/html');
    echo '<p>You need to authenticate.</p>';
    exit;
}

Когда клиент получает этот ответ, он должен вычислить возвращаемый хеш. Это достигается путем объединения имени пользователя, области и пароля и хеширования результата с помощью MD5 следующим образом:

  1. Вычислить A1MD5("username:realm:password")
  2. Вычислить A2MD5("requestMethod:requestURI")
  3. Вычислите окончательный хеш, известный как «response», как MD5("A1:nonce:A2")

Клиент отправляет ответ обратно на сервер в заголовке авторизации и включает в себя имя пользователя, область, nonce, opaque, uri и вычисленный ответ.

  Авторизация: дайджест имени пользователя = "% s", область = "% s", nonce = "% s", непрозрачный = "% s", uri = "% s", ответ = "% s" ' 

Обратите внимание, что области, nonce и opaque возвращаются на сервер без изменений.

Когда сервер получает ответ, те же шаги предпринимаются для вычисления серверной версии хэша. Если вычисленный хэш и полученные хэш-значения ответа совпадают, то запрос считается авторизованным. Это выглядит примерно так:

 <?php
$A1 = md5("$username:$realm:$password");
$A2 = md5($_SERVER['REQUEST_METHOD'] . ":$uri");
$response = md5("$A1:$nonce:$A2");

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

Улучшение оригинальной спецификации доступа к дайджесту

Теперь, когда вы знакомы с работой Digest Access Authentication из RFC 2069, давайте обратим наше внимание на некоторые из улучшений, которые были добавлены в 2617: qop, nc и cnonce.

qop , или качество защиты, указывается в заголовке WWW-Authenticate и может иметь значение «auth» или «auth-int». Если директива qop не найдена или для нее установлено значение «auth», дайджест-доступ используется только для аутентификации клиента — режим по умолчанию, который вы видели до сих пор. Когда установлено значение «auth-int», делается попытка обеспечить некоторый уровень защиты целостности ответа, и клиент также должен включать тело запроса как часть дайджеста сообщения. Это позволяет серверу определить, был ли запрос фальсифицирован при передаче между клиентом с отступом и предполагаемым сервером.

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

Число одноразовых номеров nc — это шестнадцатеричное число запросов, отправленных клиентом с данным значением одноразового номера. Таким образом, сервер может защититься от повторных атак.

С улучшениями вычисление А2 и отклика происходит примерно так:

 <?php
if ($qop == 'auth-int') {
    $A2 = md5($_SERVER['REQUEST_METHOD'] . ":$uri:" . md5($respBody));
}
else {
    $A2 = md5($_SERVER['REQUEST_METHOD'] . ":$uri");
}
$response = md5("$A1:$nonce:$nc:$cnonce:$qop:$A2");

Сильные и слабые стороны дайджест-аутентификации

Дайджест-доступ имеет некоторые преимущества по сравнению с базовой аутентификацией, так как базовая аутентификация использует открытый обмен текстовыми именами пользователей и паролями, что почти аналогично сообщению миру, какой у вас пароль. Дайджест-доступ передает хэшированное значение, а не сам пароль, поэтому он намного более безопасен, чем Basic Auth. Одноразовый номер сервера, который должен быть уникальным для каждого запроса, будет радикально изменять вычисляемый хеш при каждом новом запросе, а значение nc, предоставленное RFC 2617, помогает предотвратить атаки повторного воспроизведения, в результате чего злоумышленник может перехватить данные вашего запроса и « повторить »или повторить это как его собственный запрос.

У Digest Authentication также есть несколько недостатков. Когда RFC 2617 заменил исходную спецификацию, улучшения, которые были добавлены для обеспечения дополнительных мер безопасности между клиентом и сервером, стали совершенно необязательными, и дайджест-аутентификация будет продолжена в исходной форме RFC 2069, если она не будет реализована.

Другая проблема заключается в том, что MD5 не является сильным алгоритмом хеширования. Все, что нужно, — это время и процессор, чтобы грубо вернуть первоначальное значение к жизни. Bcrypt предпочтительнее, так как он более устойчив к атакам грубой силы. У сервера также нет возможности проверить личность запрашивающего клиента при использовании Digest Access Authentication. Это открывает возможность для человека в промежуточных атаках, когда клиента можно заставить поверить, что данный сервер действительно тот, кем он себя считает, но в итоге отправляет свои учетные данные для входа неизвестному объекту.

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

В дополнение к этой статье на GitHub есть простой пример доступа к дайджесту HTTP RFC-2069 . Если вы тот человек, который любит исследовать и возиться, смело клонируйте его. Хорошим местом для начала упражнения является внесение необходимых изменений для работы с учетными записями, хранящимися в базе данных, вместо жестко закодированных учетных данных в сценарии (помните, что для дальнейшего использования вам потребуется рассчитать и сохранить A1 как хэш пароля пользователя). найдите логин), а затем улучшите его с помощью функций RFC-2617. После этого вы получите достаточно четкое представление об аутентификации доступа к дайджесту HTTP.

Резюме

К настоящему времени у вас должно быть представление о доступных методах аутентификации HTTP.

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

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

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

Изображение через Fotolia