Как работает HTTP-аутентификация?
Аутентификация - это способ идентифицировать себя на веб-сервере. Вам необходимо предоставить доказательства того, что вы имеете право на доступ к запрошенным ресурсам. Обычно это делается с помощью комбинации имени пользователя и пароля (ключа и секрета), которые сервер проверяет, а затем решает, можете ли вы получить доступ к ресурсу.
HTTP предлагает два протокола аутентификации:
- Обычная проверка подлинности
- Дайджест-проверка подлинности
Прежде чем узнавать больше о каждом из них, давайте рассмотрим некоторые из основных понятий.
Структура аутентификации запроса/ответа
Когда кто-то отправляет запрос, вместо того, чтобы немедленно ответить на него, сервер отправляет запрос клиенту. Он требует от пользователя предоставить подтверждение личности, введя секретную информацию (имя пользователя и пароль).
После этого запрос повторяется с использованием предоставленных учетных данных, и, если они верны, пользователь получает ожидаемый ответ. Если учетные данные неверны, сервер может повторно отправить запрос или просто отправить сообщение об ошибке.
Связанные с аутентификацией заголовки запросов/ответов
Сервер выдает запрос, используя заголовок ответа WWW-Authenticate. Он содержит информацию о протоколе и области безопасности.
После того, как клиент вводит учетные данные, запрос отправляется снова. На этот раз с заголовком авторизации, содержащим алгоритм и комбинацию имени пользователя и пароля.
Если учетные данные верны, сервер возвращает ответ и дополнительную информацию в необязательном заголовке ответа Authentication-Info.
Области безопасности
Области безопасности предоставляют способ связать разные права доступа к разным группам ресурсов на сервере. Они называются защитными пространствами.
Фактически это означает, что в зависимости от ресурса, к которому вы хотите получить доступ, вам может потребоваться ввести разные учетные данные.
На сервере может быть несколько областей. Например, один может быть для статистической информации веб-сайта, доступ к которой имеют только администраторы веб-сайта. Другой вариант - изображения веб-сайтов, к которым другие пользователи могут получить доступ и загрузить изображения.
/admin/statistics/financials.txt -> Realm = "Статистика администратора"
/images/img1.jpg -> Realm = «Изображения»
Когда вы пытаетесь получить доступ к financials.txt, сервер запрашивает у вас данные для авторизации, и ответ будет выглядеть следующим образом:
HTTP/1.0 401 Unauthorized
WWW-Authenticate: Basic realm="Admin Statistics"
Пример простой HTTP-аутентификации
Теперь давайте объединим точки, рассмотрев простейший пример проверки подлинности по протоколу HTTP (обычная проверка подлинности, описанная ниже):
1. Пользовательский клиент -> Сервер
Пользователь запрашивает доступ к изображению на сервере.
GET /gallery/personal/images/image1.jpg HTTP/1.1
Host: www.somedomain.com
- Сервер -> Пользовательский клиент
Сервер отправляет пользователю запрос.
HTTP/1.1 401 Access Denied
WWW-Authenticate: Basic realm="gallery"
- Пользовательский клиент -> Сервер
Пользователь идентифицирует себя посредством ввода формы.
GET /gallery/personal/images/image1.jpg HTTP/1.1
Authorization: Basic Zm9vOmJhcg==
- Сервер -> Пользовательский клиент
Сервер проверяет учетные данные и отправляет статус 200 OK, код и данные изображения.
HTTP/1.1 200 OK
Content-type: image/jpeg
...<image data>
Не все так сложно, правда?
Теперь давайте перейдем к базовой аутентификации.
Базовая проверка подлинности (Basic)
Самый распространенный и поддерживаемый протокол. Он существует с HTTP/1.0, и каждый крупный клиент его реализует.
В приведенном выше примере показано, как пройти аутентификацию с помощью обычной аутентификации. Его довольно просто реализовать и использовать, но в нем есть некоторые недостатки безопасности.
Прежде чем перейти к вопросам безопасности, давайте посмотрим, как обычная аутентификация работает с именем пользователя и паролем.
При обычной аутентификации имя пользователя и пароль объединяются в одну строку и разделяются двоеточием (:). После этого он кодирует их, используя кодировку Base64. Несмотря на то, как это выглядит, зашифрованная последовательность символов небезопасна, и вы можете легко ее декодировать.
Целью кодировки Base64 является не шифрование, а обеспечение совместимости имени пользователя и пароля с HTTP. Основная причина этого в том, что вы не можете использовать международные символы в заголовках HTTP.
GET /gallery/personal/images/image1.jpg HTTP/1.1
Authorization: Basic Zm9vOmJhcg==
«Zm9vOmJhcg ==» из этого примера - не что иное, как строка «foo: bar» в кодировке Base64.
Таким образом, любой, кто слушает запросы, может легко декодировать и использовать учетные данные.
Хуже того, кодирование имени пользователя и пароля не поможет. Третья злонамеренная сторона по-прежнему может отправить зашифрованную последовательность для достижения того же эффекта.
Также отсутствует защита от прокси или любого другого типа атак, которые изменяют тело запроса и оставляют заголовки запроса нетронутыми.
Итак, как видите, обычная аутентификация - это далеко не идеальный механизм аутентификации.
Тем не менее, несмотря на это, вы можете использовать его для предотвращения случайного доступа к защищенным ресурсам, и он предлагает определенную степень персонализации.
Чтобы сделать его более безопасным и удобным, базовая аутентификация может быть реализована с использованием HTTPS поверх SSL, о чем мы говорим в части 5 этой серии.
Некоторые утверждают, что безопасность зависит от вашего транспортного механизма.
Дайджест-аутентификация (Digest)
Дайджест-аутентификация - более безопасная и надежная альтернатива простой, но небезопасной базовой аутентификации.
Итак, как это работает?
Дайджест-аутентификация использует криптографическое хеширование MD5 в сочетании с использованием одноразовых номеров. Таким образом, информация о пароле скрывается для предотвращения различных видов злонамеренных атак.
Это может показаться немного сложным, но станет яснее, когда вы увидите, как это работает на простом примере.
Пример Digest Authentication
1. Пользовательский клиент -> Сервер
GET /dir/index.html HTTP/1.0
Host: localhost
Клиент отправляет неаутентифицированный запрос.
2. Сервер -> Пользовательский клиент
HTTP/1.0 401 Unauthorized
WWW-Authenticate: Digest realm="shire@middleearth.com",
qop="auth,auth-int",
nonce="cmFuZG9tbHlnZW5lcmF0ZWRub25jZQ",
opaque="c29tZXJhbmRvbW9wYXF1ZXN0cmluZw"
Content-Type: text/html
Content-Length: 153
<!DOCTYPE html>
<meta charset="UTF-8" />
<title>Error</title>
<h1>401 Unauthorized.</h1>
Сервер предлагает клиенту пройти аутентификацию с использованием дайджест-аутентификации и отправляет клиенту необходимую информацию.
3. Пользовательский клиент -> Сервер
GET /dir/index.html HTTP/1.0
Host: localhost
Authorization: Digest username="Gandalf",
realm="shire@middleearth.com",
nonce="cmFuZG9tbHlnZW5lcmF0ZWRub25jZQ",
uri="/dir/index.html",
qop=auth,
nc=00000001,
cnonce="0a4f113b",
response="5a1c3bb349cf6986abf985257d968d86",
opaque="c29tZXJhbmRvbW9wYXF1ZXN0cmluZw"
Клиент вычисляет значение ответа и отправляет его вместе с именем пользователя, областью, URI, nonce, opaque, qop, nc и cnonce. Много всего.
Подробное объяснение
Давайте определим это:
- nonce и opaque - определенные сервером строки, которые клиент возвращает после их получения.
- qop (качество защиты) - одно или несколько предопределенных значений («auth» | «auth-int» | токен). Эти значения влияют на вычисление дайджеста.
- cnonce - одноразовый номер клиента, должен генерироваться, если задано qop. Он используется, чтобы избежать атак на выбранный открытый текст и предоставить сообщению защиту целостности.
- nc - счетчик одноразовых номеров, должен быть отправлен, если задано qop. Эта директива позволяет серверу обнаруживать повторы запросов, сохраняя свою собственную копию этого счетчика - если одно и то же значение nc появляется дважды, то запрос является повтором.
Атрибут ответа рассчитывается следующим образом:
HA1 = MD5("Gandalf:shire@middleearth.com:Lord Of The Rings")
= 681028410e804a5b60f69e894701d4b4
HA2 = MD5("GET:/dir/index.html")
= 39aff3a2bab6126f332b942af96d3366
Response = MD5( "681028410e804a5b60f69e894701d4b4:
cmFuZG9tbHlnZW5lcmF0ZWRub25jZQ:
00000001:0a4f113b:auth:
39aff3a2bab6126f332b942af96d3366" )
= 5a1c3bb349cf6986abf985257d968d86
Если вам интересно узнать, как вычислить ответ в зависимости от qop, вы можете найти его в RFC 2617.
4. Сервер -> Пользовательский клиент
HTTP/1.0 200 OK
Content-Type: text/html
Content-Length: 2345
... <content data>
Сервер вычисляет хэш самостоятельно и сравнивает их. Если они совпадают, он передает клиенту запрошенные данные.
Краткое резюме
Как видите, дайджест-аутентификацию сложнее понять и реализовать.
Она также более безопасна, чем обычная проверка подлинности, но все же уязвима для атаки "человек посередине". RFC 2617 рекомендует использовать вместо этого дайджест-аутентификацию базовой аутентификации, поскольку она устраняет некоторые ее недостатки. Это также не скрывает того факта, что дайджест-аутентификация по-прежнему является слабой по современным криптографическим стандартам. Ее надежность во многом зависит от реализации.
Итак, вкратце дайджест-аутентификация:
- Не отправляет пароли в виде обычного текста по сети.
- Предотвращает повторные атаки
- Защита от подделки сообщений
Некоторые из слабых мест:
- Уязвимость к атаке "человек посередине".
- Многие параметры безопасности не требуются, и поэтому дайджест-проверка подлинности будет менее безопасной, если не задана.
- Предотвращает использование надежных алгоритмов хеширования паролей при хранении паролей.
В связи с этим дайджест-аутентификация пока не получила широкого распространения. Базовая аутентификация намного проще и в сочетании с SSL еще более безопасна, чем дайджест-аутентификация.
Заключение
Мы рассмотрели различные механизмы аутентификации, которые HTTP предлагает по умолчанию, и обсудили их преимущества и недостатки.
Мы надеемся, что эти концепции больше не просто буквы на экране, и в следующий раз, когда вы услышите о них, вы точно будете знать, что это такое и когда их применять.
Вам также известно, что существуют риски безопасности, которые не устраняются этими механизмами аутентификации.