Стоит ли хешировать пароли на стороне клиента

133

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

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

Итак, мой вопрос: стоит ли хешировать пароль на стороне клиента? Это лучше, чем хеширование на стороне сервера?

Закария
источник
1
Я думал о хешировании пароля на стороне клиента, но только для того, чтобы быть уверенным, что пароль клиента никогда не существует в виде открытого текста на стороне сервера, что означает, что им будет легче, зная, что я не знаю их фактический пароль, или не может легко отказаться от него в случае компрометации. я сумасшедший?
Cyclone
1
Просто для полноты, поскольку мы говорим о безопасности, и MD5 был упомянут в OP: всегда следует использовать соль при шифровании пароля. Использование простого, несоленого MD5 ненамного лучше, чем хранение паролей в открытом виде в базе данных.
sffc 02
1
Хеширование @Cyclone ТОЛЬКО на стороне клиента - определенно плохая идея, поскольку, если злоумышленник каким-то образом знает хэш, он может использовать его для входа в систему, как если бы он знал пароль, минуя хэш-код на стороне клиента.
Teejay 01
5
@Teejay: Вот почему вы не отправляете хеш в открытом виде. Сервер отправляет случайную соль клиенту, вы добавляете хэш пароля и снова хешируете все это, а затем отправляете его обратно на сервер, который выполняет те же вычисления. Атака воспроизведения не удалась, потому что соль будет другой
MSalters
2
Разве этот вопрос не должен быть решен на security.stackexchange.com?
efr4k

Ответы:

117

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

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

На сервере:

  • генерировать несколько бит случайных
  • отправить эти биты (в открытом виде) клиенту

На клиенте:

  • генерировать несколько случайных битов
  • объединить пароль, случайные биты сервера и случайные биты клиента
  • генерировать хеш из вышеперечисленного
  • отправлять случайные биты (в открытом виде) и хеш на сервер

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

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

кортик
источник
5
Как он может аутентифицироваться с помощью хешированного пароля в системе входа в систему, если он будет снова хеширован?
Zakaria
4
Если вы храните свои пароли в хешированной форме на сервере (как и следовало бы), тогда клиенту придется дважды хешировать пароль: сначала только пароль, чтобы он соответствовал мировоззрению сервера, а затем, как описано выше для ради протокола.
Дирк
3
@Dirk, поскольку злоумышленник может обнюхивать оба пути, «случайные биты» будут перехватываться. Затем злоумышленник может проанализировать (читай: грубой силой) пару запроса и ответа в автономном режиме, чтобы найти исходный пароль.
Pacerier
7
Однако с целью отправки пароля или хэша пароля часто используется асимметричный процесс, такой как Диффи-Хеллман, для установки ключа шифрования, который позволяет обеим сторонам обмениваться информацией без возможности ее расшифровать. Это именно то, что делает SSL, и это причина того, что большинство сайтов имеют свои страницы входа на HTTPS / SSL. SSL уже защищает от атак повторного воспроизведения. Я бы рекомендовал использовать SSL, а не создавать свой собственный протокол. Хотя я согласен с солением + хешированием пароля на стороне клиента, но отправляю их через установленное SSL-соединение.
AaronLS 01
14
Чтобы было ясно: если вы не используете HTTPS, не имеет значения, какой javascript вы запускаете на клиенте; MITM сможет изменить содержимое вашей страницы до того, как оно попадет к клиенту. HTTPS - единственное решение.
Aidan
60

Прежде всего, это НЕ улучшает безопасность вашего приложения (если это веб-приложение).

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

Почему это просто. TLS решает проблему (при использовании с купленными сертификатами, а не самозаверяющими), которая довольно серьезна в криптографии: как я узнаю, что сервер, с которым я разговариваю, является сервером, с которым, как мне кажется, я разговариваю? Сертификаты TLS - это способ сказать: «Я, центр сертификации, которому доверяет ваш браузер, удостоверяю, что веб-сайт по адресу [url] имеет этот открытый ключ с соответствующим закрытым ключом, который (закрытый ключ) знает только сервер, посмотрите Я подписал подпись по всему документу, если кто менял, вы можете увидеть ".

Без TLS любое шифрование становится бессмысленным, потому что, если я сижу рядом с вами в кофейне, я могу заставить ваш ноутбук / смартфон думать, что я сервер, а MiTM (Man in The Middle) - вы. С TLS ваш ноутбук / смартфон будет кричать «НЕДОСТАТОЧНОЕ СОЕДИНЕНИЕ», потому что у меня нет сертификата, подписанного центром сертификации, который соответствует вашему сайту. (Шифрование против аутентификации).

Отказ от ответственности: пользователи, как правило, нажимают прямо на эти предупреждения: «Ненадежное соединение? Что? Мне просто нужны мои фотографии котят! Добавить исключение. Нажмите« Подтвердить », нажмите« УРА! »Котята!

Однако, если вы действительно не хотите покупать сертификат, все же ОБЯЗАТЕЛЬНО реализуйте хеширование javascript на стороне клиента (и используйте для этого стандартную библиотеку (SJCL), НИКОГДА НЕ РЕАЛИЗУЙТЕ КРИПТО САМ ).

Зачем? Повторное использование пароля! Я могу легко украсть ваш файл cookie сеанса (который позволяет мне представить вашему серверу, что я - это вы) без HTTPS (см. Firesheep). Однако, если вы добавляете javascript на свою страницу входа в систему, который перед отправкой хеширует ваш пароль (используйте SHA256 или даже лучше, используйте SHA256, отправьте им открытый ключ, который вы сгенерировали, а затем зашифруете хешированный пароль с его помощью, вы не сможете использовать соль с этим), а затем отправляет хешированный / зашифрованный пароль на сервер. ПОВТОРИТЕ хэш на вашем сервере с солью и сравните его с тем, что хранится в вашей базе данных (сохраните пароль следующим образом:

(SHA256(SHA256(password)+salt))

(также сохраните соль как открытый текст в базе данных)). И отправьте свой пароль вот так:

RSA_With_Public_Key(SHA256(password))

и проверьте свой пароль вот так:

if SHA256(RSA_With_Private_Key(SHA256(sent_password))+salt_for_username) == stored_pass: login = ok

Потому что, ЕСЛИ кто-то обнюхивает вашего клиента, они смогут войти в систему как ваш клиент (захват сеанса), но они НИКОГДА не увидят пароль в виде открытого текста (однако, если они не изменят ваш javascript, однако, хакер Starbucks, вероятно, не будет знать, как / быть заинтересованным в этом.) Таким образом, они получат доступ к вашему веб-приложению, но не к своей электронной почте / facebook / и т. д. (для которого ваши пользователи, вероятно, будут использовать один и тот же пароль). (Адрес электронной почты будет либо их логином, либо будет найден в их профиле / настройках в вашем веб-приложении).

FriendlyCryptoNeighbor
источник
Я думаю, что это хороший ответ, но, вероятно, потребуется дополнительная информация о том, как правильно солить и что лучше использовать «медленную» функцию хеширования перед сохранением пароля на сервере (например, bcrypt).
Neyt
24

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

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

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


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

dimo414
источник
Я думаю, что ваше мнение о том, что хеширование на стороне клиента только «немного лучше», верно, если вы сосредоточены исключительно на получении xпароля пользователя и доступе к одной услуге. Если учесть коллективный эффект, я бы сказал, что он «намного лучше»; потому что это предотвращает создание больших баз данных поиска паролей, используемых для перебора хэшей с солью в нескольких службах. ИМО. Посмотрите, что AWS Cognito делает в клиенте, для справки.
f1lt3r 06
17

На самом деле я не согласен с тем, что хеширование на стороне клиента в этом случае более безопасно. Я думаю, это менее безопасно.

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

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

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

Кстати, на этот вопрос, вероятно, будет больше ответов экспертов на Security StackExchange.

Адам Берли
источник
3
Полностью с этим согласен. Для того, чтобы подход на стороне клиента работал, нужно также отправить соль клиенту, что сделает недействительной всю цель соления!
Джеймс Райт
@JamesWright: Дело в том, что для каждого использования отправляется случайная соль, что предотвращает незаконное повторное использование сообщений входа в систему. (Форма повторных атак). Посылать каждый раз одну и ту же соль действительно бессмысленно.
MSalters
Что вам нужно сделать, так это использовать «одноразовый номер» ( en.wikipedia.org/wiki/Cryptographic_nonce ). Таким образом, сервер также контролирует соль и обеспечивает безопасность. Хеширование на стороне клиента также важно, чтобы внедренный код JS не мог легко найти его позже. Подробнее здесь: stackoverflow.com/a/21716654/43615
Томас Темпельманн,
Чтобы узнать об использовании соли + nonce в процессе аутентификации при входе в систему, см. Этот ответ: stackoverflow.com/a/24978909/43615
Томас Темпельманн,
Очевидно, что если вы хешируете его на стороне клиента, вам придется снова хешировать его на стороне сервера, чтобы предотвратить вывод, который вы делаете. Однако, как отмечают другие, для конфиденциальности вам уже нужно шифрование на стороне клиента.
Даниэль Метнер
5

Обратите внимание, что защита паролей от третьих лиц - это еще не все.

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

Следовательно, хеширование / шифрование на стороне клиента имеет смысл.

Рафаэль
источник
Согласовано! Многие упускают этот момент. Если я загружу вашу базу паролей с солеными хешированными паролями и смогу взломать только один, используя базу данных хеш-поиска, то, скорее всего, я смогу взломать их все. Как только у меня будет 50 тысяч исходных паролей, у меня теперь есть ключ для xпользователей nслужб, которые шифруют только на сервере. Если каждая служба уникальным образом хэширует пароль перед тем, как покинуть клиента, большая база данных межсервисных паролей становится намного меньше. Проверьте свой входной трафик AWS, посмотрите, что они делают. Вероятно, мой дорогой Ватсон.
f1lt3r 06
1

В последнее время я много работал над этим, IRL есть две проблемы с хешем / симметричным шифрованием на стороне клиента, которые действительно убивают идею: 1. Вы должны вернуть соль на сервер КАК-ТО ... и зашифровать на стороне клиента вам понадобится пароль ... что противоречит цели. 2. Вы раскрываете свою реализацию хеширования (это не ОГРОМНАЯ сделка, поскольку большинство сайтов используют один из 3 или 4 алгоритмов хеширования), что упрощает атаку (просто нужно попробовать один, а не n).

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

ГЛАВНОЕ преимущество этого заключается в том, что мне никогда не нужно хранить данные пользователей / даже в незашифрованной памяти на моем сервере / хранилище данных (а закрытый ключ моего сервера физически отделен)

Основа этого заключалась в том, чтобы предоставить людям способ безопасного общения там, где HTTPS был ограничен (например, Иран / Северная Корея и т.д.), а также просто забавный эксперимент.

Я ДАЛЕКО от первого, кто подумал об этом, http://www.mailvelope.com/ использует это

ScottGal
источник
1

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

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

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

Данные пользователей зашифрованы и на стороне браузера.

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

Несколько небольших примеров обоих этих методов есть в моем блоге http://glynrob.com/javascript/client-side-hashing-and-encryption/

GlynRob
источник
1

Недавно и GitHub, и Twitter объявили, что пароли хранятся во внутренних журналах. У меня такое случалось непреднамеренно в отчетах об ошибках и других журналах, которые попали в splunk и т. Д. Для твиттера, если пароль Трампа был в журнале, это могло быть большим делом для администратора, чтобы его «увидеть», для других сайтов, вероятно, не так большое дело, поскольку администраторы не будут в этом много пользы. Мы, админы, не любим видеть пароли.

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

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

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

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

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

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

Учти это:-

Клиент отправляет серверу запрос «У меня есть пароль для проверки».

Сервер отправляет клиенту одноразовую случайную строку. R $

Клиент вставляет пароль пользователя в эту строку (на основе любых (переменных) правил, которые вы хотите применить).

Клиент отправляет строку на сервер, и если пароль в порядке, сервер регистрирует пользователя.

Если сервер получит еще один запрос на вход с использованием R $, пользователь выходит из системы, и учетная запись замораживается в ожидании расследования.

Очевидно, будут приняты все другие (обычные) меры безопасности.

cneeds
источник
0

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

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

n8isjack
источник