Должен ли я хешировать пароль перед его отправкой на сервер?


110

Я заметил, что большинство сайтов отправляют пароли в виде обычного текста по HTTPS на сервер. Есть ли преимущество, если вместо этого я отправлю на сервер хеш пароля? Было бы безопаснее?


5
@Jader Dias: Я знаю, что вы не спрашивали об этом, но это не сделает более безопасным, если вы его хэшируете, ТОГДА отправьте его по https. Фактически, это может сделать его менее безопасным, поскольку вы обнажаете свою соль. Кроме того, (говоря о моей обратной стороне здесь), смешение алгоритмов может вызвать больше хеш-коллизий и сделать его более взломанным.
Мерлин Морган-Грэм

@Merlyn "хеш-коллизии" хороший момент!
Jader Dias

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

@JJ «Алгоритмы смешивания вообще не увеличивают вероятность столкновения». Мне бы очень хотелось увидеть подтверждение этому утверждению. Позвольте мне вас остановить: это неверно , в целом это увеличивает количество столкновений. Я могу легко построить хеш-функцию так, чтобы h (x) не было константой 0, а h (h (x)) = 0 для всех x. Поэтому вам нужно будет обратиться к точному набору алгоритмов хеширования и к тому, как вы их смешиваете. Тогда вам нужно будет доказать свое заявление. AFAIK даже для нескольких SHA (с солью) это открытая проблема. И в основном мы верим, что это правда. Криптография - это сложно.
причудливый

Ответы:


155

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

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

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

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

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

Итак, у нас есть ключ. Теперь нам нужно удалить любые следы пароля на клиентском устройстве.

Затем нам нужно получить этот ключ к вашим системам. Никогда не следует передавать ключ или пароль «в открытом виде». Даже по HTTPS. HTTPS не является непроницаемым. Фактически, многие организации могут стать доверенным MITM - не с точки зрения атаки, а для выполнения проверок трафика для реализации своих собственных политик безопасности. Это ослабляет HTTPS, и это не единственный способ, которым это происходит (например, перенаправление на HTTP-атаки MITM). Никогда не думайте, что это безопасно.

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

На этом этапе я бы необратимо хешировал его в последний раз, прежде чем он навсегда сохранится в ваших собственных системах. Таким образом, вы можете поделиться "солью" учетных данных с партнерскими организациями для целей SSO и т.п., в то же время имея возможность доказать, что ваша собственная организация не может выдавать себя за пользователя. Лучшая часть этого подхода заключается в том, что вы никогда не делитесь ничем, созданным пользователем без его разрешения.

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

TL; DR:

Используйте HTTPS. Надежное хеширование паролей, необратимое, с уникальной солью для каждого пароля. Сделайте это на клиенте - не передавайте их фактический пароль. Передача исходного пароля пользователя на ваши серверы никогда не бывает «ОК» или «Хорошо». Удалите все следы исходного пароля. Используйте одноразовый номер независимо от HTTP / HTTPS. Это намного безопаснее на многих уровнях. (Ответ на ОП).


26
Я только что проверил gmail и facebook - инструменты разработчика Chrome сообщают мне как POST с urlencoded сообщением, содержащим мое имя пользователя и пароль в виде простого (несоленого) текста. Как / почему крупные игроки не используют одноразовую засолку на клиенте?
gremwell

18
Вы хешируете ключ с помощью одноразового номера и заявляете, что можете отменить одноразовый номер на стороне сервера. Значит, вы брутфорсируете хеш? Или как получить одноразовый номер, когда вы получили хэш = ХЭШ (секрет + одноразовый номер). ХЭШ должен быть необратимой функцией. Вы реализовали это? Я не думаю, что то, что вы объясняете, возможно. Можете ли вы создать блок-схему протокола?
Silver

20
Если вы не доверяете HTTPS, все усилия бессмысленны! Сам ваш код доставляется по сети, и злоумышленник может изменить / заменить все ваши попытки защитить пароль при передаче
Саджид Калла,

3
MitM, который может перезаписать сертификат, может перезаписать одноразовый номер. Или что сказал Саджид.
Leewz

4
Если вас беспокоит MITM с HTTPS, какой смысл отправлять соль клиенту, чтобы клиент мог солить пароль перед передачей хэша обратно на сервер? Кажется бессмысленным. Можно также просто выполнить несоленый хэш на сервере, а затем снова использовать соль для хеширования на сервере. Ясно, что клиент не может быть генератором клиентской соли, потому что при следующем входе в систему он будет другим и не будет вычислять тот же хэш на стороне сервера.
давка

24

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


5
Это не должно быть проблемой. Если клиент использует прокси, то все, что увидит прокси, - это зашифрованные данные HTTPS. Если вы говорите об атаке «злоумышленник посередине», правильно настроенный сертификат должен предотвратить это.
Кирстен Арнольд 02

7
@Jader: Никакие манипуляции с данными не остановят MITM-атаку, поскольку она может просто передавать все, что к ней приходит. Неважно, передаете ли вы пароль или хеш. Это совсем другое дело.
Дэвид Торнли

2
Цель SSL (HTTPS = HTTP через SSL) - препятствовать MITM.
yfeldblum 02

1
@carnold - MINTM - А как насчет перенаправления на http? Заметило бы большинство людей? sslstrip - securityfocus.com/brief/910
nate c

1
@Jader Dias, ты пытаешься решить проблему, которой не существует. HTTPS решает эту проблему, хэш на стороне клиента не добавляет безопасности. Клиенту нельзя доверять.
ладья

17

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

Весь смысл хеширования паролей состоит в том, чтобы добавить дополнительный уровень безопасности. Если злоумышленник может получить хэш и соль из базы данных с помощью SQL-инъекции или небезопасной резервной копии, он должен найти простой текст путем грубой силы. John The Ripper обычно используется для взлома хэшей паролей.

Отказ от использования https является нарушением OWASP Top 10: A9-Недостаточная защита транспортного уровня

РЕДАКТИРОВАТЬ: если в своей реализации вы вычисляете a, sha256(client_salt+plain_text_password)а затем вычисляете другой хэш на стороне сервера, sha256(server_salt+client_hash)это не является серьезной уязвимостью. Однако он по-прежнему подвержен перехвату и воспроизведению запроса. Таким образом, это все еще явное нарушение WASP A9. Однако в качестве уровня безопасности по-прежнему используется дайджест сообщения.

Самое близкое, что я видел к замене https на стороне клиента, - это различие в обмене ключами в javascript . Однако это предотвращает активные атаки MITM и, таким образом, по техническим причинам является нарушением OWASP A9. Авторы кода согласны с тем, что это не полная замена HTTPS, однако это лучше, чем ничего и лучше, чем система хеширования на стороне клиента.


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

@Rook использует обмен ключами diffie-hellman вместе с https - это "бесполезное" решение? (Я имею в виду, что мы можем использовать только https, а diffie helman не увеличивает безопасность imao)
Мишель Гокан

@Michel Kogan обмен ключами DH может использоваться в HTTP вместе с другими инструментами.
ладья

1
@Rook Лучше всего применять хеш на сервере, поэтому я думаю, вам следует обновить начало своего ответа, чтобы не отклонять хеширование на стороне клиента, и только затем упомянуть, что хеши и соли, хранящиеся на сервере, никогда не должны отображаться.
Левенте Панцель

8

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


2
Это кажется полной чушью ... Чем хэш менее безопасен, чем пароль?
Левенте Панцель

1
Это верно только для «тупых» хешей. Подумайте об этом: сервер отправляет клиенту соль S, а клиент выполняет HASH (S + PASSWORD) и отправляет его на сервер. Сервер учитывает этот конкретный хэш только для текущего сеанса. Злоумышленник действительно может отправить хэш и забыть пароль, но ТОЛЬКО ДЛЯ ТЕКУЩЕЙ СЕССИИ. Поэтому это более безопасно, чем простой текст.
Hello World

Обновление: проверка подлинности доступа к дайджесту стала еще более сложной: en.wikipedia.org/wiki/Digest_access_authentication
Hello World

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

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

5

Пароль в виде открытого текста никогда (даже при использовании HTTPS) не покидает клиента. Он должен быть необратимо хеширован перед тем, как покинуть клиент, поскольку серверу не нужно знать фактический пароль.

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

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

Мой подход к проблеме в веб-приложении на основе сокетов, которое я создаю, заключается в том, что при подключении к клиенту сервер генерирует соль (случайную строку, добавляемую перед хешированием) и сохраняет ее в переменной сокетов, а затем передает этот хеш клиенту. Клиент берет пароль пользователя, хеширует его, добавляет соль с сервера и хеширует все это перед передачей на сервер. Затем он отправляется на сервер, который сравнивает этот хеш с хешем (хеш в БД + соль). Насколько я знаю, это хороший подход, но, честно говоря, я мало читал по этой теме, и если я ошибаюсь в чем-то, я хотел бы исправить это :)


3

Используйте HTTP-дайджест - он защищает пароль даже через http (но лучше всего использовать http-дайджест через https)

Википедия:

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

Ссылка: http://en.wikipedia.org/wiki/Digest_access_authentication

Если вы хотите увидеть использование в «реальной жизни», вы можете посмотреть на phpMyID - провайдер php openid, который использует дайджест-аутентификацию http http://siege.org/phpmyid.php

.. или вы можете начать с образцов php auth на http://php.net/manual/en/features.http-auth.php

Дайджест http rfc: http://www.faqs.org/rfcs/rfc2617

Судя по моим тестам, все современные браузеры его поддерживают ...


HTTP Digest реализует то, что я имел в виду в этом вопросе, но будет ли у нас какое-либо преимущество, если мы будем использовать HTTPS Digest (SSL + HTTP Digest)?
Jader Dias

Одно из основных различий будет заключаться в том, что все отправляется / принимается в зашифрованном виде - отправка и получение заголовков http и ответ html. Для кого-то, случайно пытающегося «взломать» ssl с помощью атаки «человек посередине», http-дайджест будет дополнительным мотивом, чтобы заставить его искать другую более легкую цель, или, если он регистрирует весь захваченный трафик, ваши пароли все еще безопаснее. Возможно, я неправильно понял вопрос, английский - не мой родной язык.
влад б.

Хеширование пароля имеет одно большое преимущество: если трафик каким-либо образом регистрируется или захватывается, это усложняет работу этого человека. Кроме того, с дайджестом http, если ssl не всегда требуется, вы можете позволить пользователям выбирать между http и https. Или вы можете использовать разные протоколы для разных серверов (например, я не применяю https для просмотра / изменения меньшего количества важных данных (имя пользователя, загрузка аватара), но применяю https для выставления счетов и других частей сайта (таким образом я могу уменьшить нагрузку на некоторые серверы, если / когда необходимо)
влад Б.

3

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

Однако простое обфускация пароля на стороне клиента (не хэш), отправляемая по HTTPS, имеет определенное значение. Если не ошибаюсь, эту технику действительно используют некоторые банки. Целью этого метода не является защита пароля от перехвата через провод. Скорее, это делается для того, чтобы пароль не использовался глупыми шпионскими инструментами и плагинами браузера, которые просто захватывают каждый запрос HTTPS GET / POST, который они видят. Я видел файл журнала, захваченный с вредоносного веб-сайта, который содержал 400 МБ случайных транзакций GET / POST, захваченных из пользовательских сеансов. Вы можете себе представить, что веб-сайты, использующие только HTTPS, будут отображаться с паролями в виде открытого текста в журнале, но веб-сайты с очень простой обфускацией (ROT13) также будут отображаться с паролями, которые не используются немедленно.


«но веб-сайты с очень простой обфускацией (ROT13) также будут отображаться с паролями, которые не используются немедленно» - это противоречит исходному утверждению. Ключ в том, что они не используются СРАЗУ, но это действительно бесполезно. Пароль и его ROT13 эквивалентны. НО, если вы используете SHA2 пароль, он не будет присутствовать в журналах (так что ваши администраторы не узнают возможные пароли пользователей к другим системам), и вы больше НЕ нарушаете почти все законы о конфиденциальности.
Левенте Панцель

2

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


Прокси-серверы не перехватывают эти данные?
Jader Dias

Насколько я понимаю, они это делают, но прокси не несет ответственности за шифрование / дешифрование, и, если это не недобросовестный прокси, только передает данные. Тип и надежность шифрования зависят от того, что сервер и клиент могут поддерживать.
jac

1
Даже если прокси недобросовестен, он не может расшифровать данные, поскольку они зашифрованы с использованием открытого ключа сервера. Единственный способ, которым прокси-сервер может расшифровать данные, - это подделать сертификат сервера с помощью другого ключа,
Кирстен Арнольд

@Jader. Если бы они это сделали, это сделало бы HTTPS довольно слабым. когда вы аутентифицируетесь на сервере с HTTPS, вы получаете гарантию (при условии, что сертификат действителен), что вы подключаетесь к определенному серверу и имеете зашифрованный путь от одного конца до другого. Гипотетически, атаковать человека посередине, конечно, можно, чтобы обмануть вас, но это не то же самое, что и обычный веб-прокси.
Питер Рекор 02

2

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

Сделайте оба

Сделайте и то, и другое, потому что:

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

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

Конечно, они могли бы нанести много другого вреда, если бы у них была свобода чтения из вашей базы данных.

Я просто хочу подчеркнуть здесь, что если вы решите хешировать ключ перед уходом от своих клиентов, этого недостаточно - бэкэнд-хеширование, я думаю, гораздо важнее, и вот почему: если кто-то перехватывает трафик с вашего client, то они увидят содержимое passwordполя. Неважно, хеш это или простой текст - они могут скопировать его дословно, чтобы выдать себя за авторизованного клиента. (Если вы не выполните шаги, описанные в @ user3299591, и я рекомендую вам это сделать). С другой стороны, хеширование столбца БД является необходимостью и совсем не сложно реализовать.



0

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

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


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

@Jader, дело в том, что злоумышленнику сейчас нужен только первый хеш, а не пароль. Фактически, хеш-код, который вы получаете от пароля на стороне клиента, теперь так же полезен, как и сам пароль. Таким образом, вы не получаете особой безопасности.
Питер Рекор 02

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

0

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

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

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

Если злоумышленник получил доступ к базе данных, возможно, через копию резервной копии, тогда вам нужно убедиться, что он не может войти в систему, имея только эти знания. Если, например, вы сохранили хэш с именем для входа как hash(login_name+password), и вы передали тот же хеш от клиента для прямого сравнения, тогда злоумышленник может выбрать пользователя случайным образом, отправить хэш, прочитанный из базы данных и войти в систему как этот пользователь, не зная пароля, увеличивает масштаб нарушения. В этом случае отправка пароля в виде открытого текста была бы более безопасной, поскольку злоумышленнику необходимо было бы знать открытый текст для входа в систему, даже имея копию базы данных. Вот где реализация является ключевой. Независимо от того, отправляете ли вы пароль в виде открытого текста или хеш-код этого пароля на стороне клиента, вы должны хешировать это значение на стороне сервера и сравнивать этот хэш с хешем, хранящимся в записи пользователя.

Концепции, о которых следует помнить:

  • Вы «солируете» хэш, добавляя к вашему хешу какое-то уникальное значение, обычно уникальное для строки. Его цель - гарантировать уникальность хэшей друг от друга, даже если значения открытого текста, которые они представляют, одинаковы, поэтому два пользователя с одним и тем же паролем все равно будут иметь разные хеши. Не нужно хранить соль в секрете.
  • При аутентификации всегда хешируйте на стороне сервера любое значение, которое вы передаете от клиента в качестве пароля (даже если оно уже хешировано), и сравнивайте его с предварительно хешированным значением, хранящимся в базе данных. Для этого может потребоваться сохранение версии исходного пароля с двойным хешем.
  • Когда вы создаете хэш, подумайте о добавлении уникальной соли для сервера / кластера в хэш, а также уникальной соли для строки, чтобы защититься от сопоставления любых предварительно вычисленных хешей в таблицах поиска.
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.