Можно ли хешировать пароль и аутентифицировать пользователя на стороне клиента?

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

Мне интересно, есть ли способ аутентифицировать пользователя, хешируя его пароль на клиенте, а не отправляя его в виде открытого текста по сети без использования SSL.

Я понимаю, что это применимо только для пользователей с включенным Javascript.

Или ... возможно, это была бы отличная встроенная возможность для Silverlight (есть ли это в дорожной карте Silverlight?)


РЕДАКТИРОВАТЬ: Я также ищу «степени безопасности». Это означает, что если есть метод, который имеет некоторые преимущества перед простой отправкой пароля в виде обычного текста, я хотел бы знать, что это такое и почему.

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


person Feckmore    schedule 06.07.2009    source источник
comment
Как это может быть безопаснее, чем отправка открытого текста по сети? Вы по-прежнему подвергаете данные злоумышленникам, которые могут быть использованы для взлома учетной записи этого пользователя.   -  person Adamski    schedule 06.07.2009
comment
Как говорит Адам, злоумышленник может захватить хэш, отправленный пользователем, и пройти аутентификацию, используя тот же хеш.   -  person Tom Mayfield    schedule 06.07.2009
comment
Сервер должен предоставлять уникальную соль для каждого запроса.   -  person Landon Kuhn    schedule 06.07.2009
comment
@Adamski - Я не совсем уверен, что это будет безопаснее, чем открытый текст ... вот в чем вопрос. Одно из преимуществ, упомянутых ниже, заключается в том, что для незначительных сайтов (таких как местный кулинарный клуб) пользователь избегает отправки своего пароля в виде простого текста, который для многих пользователей является тем же паролем, который они используют для доступа к адресу электронной почты, который также является их логином.   -  person Feckmore    schedule 06.07.2009
comment
Это защищает от человека посередине, который украдет пароль и использует его позже, но не защищает от человека посередине, который украдет аутентификацию и использует ее сейчас. SSL, IIRC, действительно защищает от этого (дыры в безопасности DNS означают, что эта защита ошибочна) за счет использования ранее существовавших ключей на вашем компьютере в качестве частичного тестирования того, что сервер является тем, кем он является, а не кем-то посередине, подделывающим сервер.   -  person Brian    schedule 06.07.2009


Ответы (6)


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

  1. Общий алгоритм хеширования как на клиенте, так и на сервере.
  2. Одноразовое значение соли, генерируемое на сервере и передаваемое клиенту.
  3. Исходный пароль хранится в базе данных.

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

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

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

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

Ссылки (для тех, кто никогда не слышал о Kerberos или SRP):

http://en.wikipedia.org/wiki/Kerberos_(protocol) http://en.wikipedia.org/wiki/Secure_remote_password_protocol

person jrista    schedule 06.07.2009
comment
не изобретайте заново протоколы аутентификации, повторно используйте хорошо зарекомендовавшие себя - person Remus Rusanu; 06.07.2009
comment
Не мог бы кто-нибудь объяснить, почему это было отклонено? Это вполне допустимая практика аутентификации, которая десятилетиями использовалась во многих системах. - person jrista; 06.07.2009
comment
@Remus: Это не новый протокол, это хорошо зарекомендовавший себя. Это часть Kerberos, которая обеспечивает безопасную аутентификацию в незащищенной сети. en.wikipedia.org/wiki/Kerberos_(protocol) Механизм хеширования пароля называется SRP, протокол безопасного удаленного пароля. en.wikipedia.org/wiki/Secure_remote_password_protocol - person jrista; 06.07.2009
comment
По своим ссылкам посмотрите на недостатки. Похоже, это хороший список для интернет-клиентов? Требования к часам? en.wikipedia.org/wiki/Kerberos_(protocol)#Drawbacks - person Tim Hoolihan; 06.07.2009
comment
@Tim: Kerberos был просто примером системы, использующей SRP. Фактический описанный механизм обмена паролями не является протоколом Kerberos и поэтому не страдает от всех его недостатков. Kerberos - это система более высокого уровня, использующая SRP, но SRP - это просто очень простая система безопасного обмена паролями, которую я описал. - person jrista; 06.07.2009
comment
@jrista: Честно говоря, могут быть другие системы аутентификации, которые могут справиться с этим сценарием. Я думаю, однако, что суть в том, что это, кажется, больше риска, усилий и затрат (с учетом времени разработчика), чем SSL. - person Tim Hoolihan; 06.07.2009
comment
@Tim: Согласен, как отмечалось в последнем комментарии в моем исходном сообщении о том, что это ненужно и слишком сложно, если вы используете SSL. Я стараюсь отвечать на вопросы людей независимо от моего личного мнения по этому поводу. Хотя SSL действительно является лучшим вариантом, я не могу сказать, каковы требования человека, задающего вопрос, или почему эти требования существуют. Лучше поделиться полезными знаниями, чем скрыть их из-за личных предубеждений. - person jrista; 08.07.2009

Это плохая идея с точки зрения безопасности. Если вы отправляете не-ssl-форму, содержащую хешированный пароль, то у любого, кто перехватывает трафик, есть все необходимое для входа в систему. Ваш javascript должен приводить к чему-то, что указывает на успех (перенаправление, токен, переданный на сервер, и т. Д.). Как бы то ни было, теперь слушатель может воссоздать это без надлежащей аутентификации.

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

Добавлено для ясности:

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

<form action="signin.whatever" method="post">
<input type="text" id="txtUser">
<input type="text" id="txtPass">
<input type="hidden" id="hiddenHash">
<input type="submit" onclick="hashAndSubmit()">
</form>

где hashAndSubmit () хеширует пароль и помещает его в hiddenHash, а поле пароля вычеркивает. Если я понюхаю ваше сообщение и увижу следующие поля:

txtUser:joeuser
txtPass:
hiddenHash:xxx345yz   // hash result

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

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

Доверяю ли я себе больше, чем годы и годы публичного тестирования шифрования SSL?

person Tim Hoolihan    schedule 06.07.2009
comment
Почему Javascript (или другой сценарий на стороне клиента) должен указывать на успех? Почему он не может просто отправить хешированный пароль на сервер для сравнения с сохраненным хешированным паролем вместо того, чтобы отправить простой текстовый пароль для хеширования на стороне сервера, а затем для сравнения? - person Feckmore; 06.07.2009
comment
это либо, либо. если вы хэшируете на клиенте, то пароль больше не имеет значения, потому что злоумышленник может обнюхать хешированный пароль и провести атаку с повторением. если вы аутентифицируетесь на клиенте, вам нужно только ответить токеном успеха. В любом случае у вас есть проблема. - person Tim Hoolihan; 06.07.2009
comment
Дело не только в том, что я доверяю себе, это скорее связано с тем, что я, возможно, искренне игнорирую решение, о котором я не слышал ... поэтому я спрашиваю. И мне интересно узнать о степени безопасности, а не только о том, что является только максимальной безопасностью (как я только что отметил в своем обновлении). - person Feckmore; 06.07.2009
comment
Чтобы немного прояснить мое невежество, можно ли смягчить упомянутую вами атаку воспроизведения путем отслеживания имени хоста или других идентифицирующих данных сеанса? Или это небезопасно? - person Feckmore; 06.07.2009
comment
Что-нибудь подобное было бы полезно, особенно если вы получите это из конвейера IIS вместо переменных формы. Тем не менее, в середине атаки есть человек, и в игру может вступить спуфинг. Я не хотел подразумевать незнание или звучать резко, извините, если это так, просто передаю извлеченные уроки. - person Tim Hoolihan; 07.07.2009
comment
Нет, вы не имеете в виду незнание, я просто люблю переоценивать свое невежество ... если это вообще возможно. Хотя я согласен с вашим ответом, я выбираю @ jrista для потомков, потому что считаю, что он наиболее прямо отвечает на вопрос, а затем указывает на недостатки. - person Feckmore; 16.07.2009

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

person Draemon    schedule 06.07.2009

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

person Landon Kuhn    schedule 06.07.2009

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

person VolkerK    schedule 06.07.2009

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

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

person Remus Rusanu    schedule 06.07.2009