Как управлять паролями в веб-приложениях?

Каков современный метод сохранения паролей пользователей в веб-приложениях? Я работаю с Java 6 + MySQL. Вот некоторые из вопросов, которые я имею в виду: что лучше: кодировать в приложении или с помощью СУБД (актуально ли это вообще)? Какой алгоритм считается надежным? Что хранить в базе данных? На самом деле новичок в этом материале, поэтому, возможно, пропустил некоторые важные детали, и в этом случае, пожалуйста, не стесняйтесь сообщить мне.

Спасибо.


person kooker    schedule 16.03.2011    source источник
comment
Я думаю, что общая структура хеширует пароль на стороне клиента или сервера и хранит хеш в базе данных. Этот хеш используется на случай взлома базы данных.   -  person Spidy    schedule 16.03.2011


Ответы (3)


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

Для этого необходимо сделать следующее:

  1. Используйте безопасный алгоритм хеширования, который еще не сломан (предпочтительно SHA-512, Sha1 и MD5 не работают)
  2. Объедините имя пользователя + пароль + соль (соль должна быть относительно длинной постоянной строкой, которая остается неизменной на протяжении всего вашего приложения и предотвращает атаки Rainbow с некоторыми усилиями)
  3. SHA-512 результат объединения и сохранить его в базе данных.
  4. каждый раз, когда пользователь пытается войти в систему, хешируйте свои учетные данные, используя один и тот же метод, и сверяйте их с данными в базе данных, если такие же, они верны.

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

person AbiusX    schedule 16.03.2011
comment
-1: вам нужна соль на хеш, а не на приложение. Это значительно усложняет создание радужных таблиц. Соль для каждого приложения мало что дает. Радужную таблицу для общих слов можно вычислить за день или около того. - person Andrew Moore; 16.03.2011
comment
Нет большой разницы, если одной соли достаточно. Соль в том, чтобы предотвратить атаки по словарю. - person AbiusX; 16.03.2011
comment
Я думаю, вы имеете в виду правильные вещи, но вы, возможно, захотите уточнить свой язык, чтобы указать, что соль должна быть другой, но постоянной строкой для каждого хешируемого пароля. Под константой ... то же самое на протяжении всего времени в вашем приложении, я предполагаю, вы не подразумеваете одно постоянное значение, охватывающее все строки, которые должны быть хешированы. - person Ken Redler; 16.03.2011
comment
@AbiusX: Длина соли не имеет значения. Если ваше приложение скомпрометировано (или декомпилировано на Java), ваша соль известна и ваша защита отключена. Однако, если вы генерируете случайную соль для каждого хэша, даже если ваша соль хранится вместе с вашим хешем, для каждого пароля, который вы хотите узнать, необходимо построить радужную таблицу. - person Andrew Moore; 16.03.2011
comment
Вы также можете хешировать пароль в клиентском браузере, чтобы не отправлять пароль через Интернет в открытом виде, если вы не используете HTTPS (см. jssha.sourceforge.net, чтобы библиотека JS выполняла SHA). - person WhiteFang34; 16.03.2011
comment
@ WhiteFang34: Это бессмысленно. Злоумышленник может просто подделать запрос с хешированным паролем и в любом случае получить доступ. - person Andrew Moore; 16.03.2011
comment
@ WhiteFang34: это не добавляет безопасности, так как злоумышленник также отправит хэш пароля вместо исходного прохода, то есть пароль теперь является его хешем. - person AbiusX; 16.03.2011
comment
@ Андрей: не могли бы вы указать мне, насколько длина соли бессмысленна и как злоумышленник, зная, что ваша соль, может нарушить защиту? - person AbiusX; 16.03.2011
comment
@AbiusX: Зная вашу соль, я могу просто создать ОДНУ радужную таблицу и сравнить с ней все ваши пароли. Длина вашей соли не мешает мне создать радужную таблицу или нет. Кроме того, есть вероятность, что если у меня есть доступ к вашей базе данных, у меня будет доступ к вашему коду, где хранится ваша безопасная соль. Этого не может произойти с солью для каждого пароля. Мне нужно создать радужную таблицу для каждого пароля, и это требует больших затрат времени (даже более затратно с медленным алгоритмом, таким как bcrypt). - person Andrew Moore; 16.03.2011
comment
@Andrew: Вы знаете, что создание Rainbow Table требует не меньше усилий, чем взлом хеша? Это не вариант. Радужные таблицы обычно полезны при создании и использовании для всех хэшей O (2 ^ n) / O (2 ^ n) = O (1). Также соли не предназначены для обеспечения безопасности. - person AbiusX; 16.03.2011
comment
@AbiusX: Каждый эксперт по безопасности скажет вам именно то, что я говорю: используйте медленный алгоритм, не используйте повторно один и тот же хэш. Соли используются, чтобы усложнить создание радужных таблиц. - person Andrew Moore; 16.03.2011
comment
Хеширование пароля в клиентском браузере не совсем бессмысленно. Он защищает конечных пользователей, которые обычно используют один и тот же пароль для разных сайтов. Представьте, например, что они использовали свой пароль Gmail, а логин - это их адрес Gmail. Злоумышленник посередине теперь может украсть их учетную запись Gmail. Тогда как если бы он был хеширован специально для сайта, он был бы хорош только для этого сайта. Да, это никак не способствует безопасности вашего собственного сайта. - person WhiteFang34; 16.03.2011
comment
en.wikipedia.org/wiki/Cryptographic_salt#Additional_benefits Оцените это. Также вы можете посетить веб-сайт OWASP, я считаюсь мировым экспертом по безопасности. - person AbiusX; 16.03.2011
comment
@AbiusX: OWASP рекомендует bcrypt по указанным выше причинам. - person Andrew Moore; 16.03.2011
comment
@WhiteFang: в вашем сценарии все верно, но радужные таблицы разрушают этот сценарий. @ Андрей: ты читал сообщение в Википедии? - person AbiusX; 16.03.2011
comment
@AbiusX: Я предпочитаю не основывать безопасность на том, что говорит Википедия. - person Andrew Moore; 16.03.2011
comment
@Andrew: Я не говорю, что это правда, потому что так говорится в вики. Ниже перечислены причины. И я сказал вам, почему ваше предположение неверно. Почему ты такой упрямый? - person AbiusX; 16.03.2011
comment
@AbiusX: каждый пароль OWASP ... правы, я неправ ... Оскорбления и непроверенные источники (которые говорят прямо противоположное тому, что вы говорите) действительно помогли вам выразить свою точку зрения. - person Andrew Moore; 16.03.2011
comment
@ Андрей: пожалуйста, проверьте свою ссылку еще раз. :) - person AbiusX; 16.03.2011
comment
@AbiusX: Сохраняет хешированное значение пароля. Посолите каждый хэш. Предпочтительно использовать различную случайную соль для каждого хэша пароля вместо постоянной длинной соли. Никогда не храните пароль в открытом виде или зашифрованную версию пароля. Криптографическая структура для хеширования паролей описана в PKCS # 5 v2.1: Стандарт криптографии на основе пароля. Существуют специальные алгоритмы безопасного хеширования паролей, такие как bcrypt, scrypt. - person Andrew Moore; 16.03.2011
comment
Да, как вы видите, там написано «предпочтительно», как я уже сказал. Это не обязательно. - person AbiusX; 16.03.2011
comment
@AbiusX: продвигая ценность хеширования на стороне клиента, сервер может предоставить две соли: одну, которая остается неизменной для данного пользователя (U), и другую, которая меняет каждый сеанс (S). Клиент хеширует пароль пользователя с помощью соли U, а затем хеширует его с помощью соли S. Сервер считывает хэш из базы данных (который только с солью U, когда пользователь устанавливает свой пароль) и хеширует его с помощью S для сравнения для проверки. Теперь радужные таблицы не могут быть применены, и хэш, отправленный по сети, полезен только на время сеанса. - person WhiteFang34; 16.03.2011
comment
@AbiusX - нет, не обязательно. на самом деле засолка любого типа не является обязательной. черт возьми, даже хеширование не является обязательным. мы могли бы просто хранить пароли в виде обычного текста. с другой стороны, хеширование немного безопаснее, чем обычный текст, поэтому было бы предпочтительнее. и посолить хэш немного безопаснее, поэтому, вероятно, это также предпочтительнее. и, видя, что использование различных солей для каждого хэша пароля предпочтительнее, чем использование постоянной длинной соли, в соответствии с ожиданиями людей, разбирающихся в безопасности, не будет ли логическим выводом, что это действительно более безопасно? - person Franci Penov; 16.03.2011
comment
@AbiusX - и если есть возможность быть более безопасным, почему вы утверждаете, что человек, рекомендующий этот выбор, ошибается и OP должен оставаться с менее безопасным (согласно OWASP) выбором? Во всяком случае, я мог бы попытаться назвать такую ​​рекомендацию потенциально слишком дорогой для конкретных сценариев (и этот вопрос не является одним из таких сценариев), но я никоим образом не мог понять, насколько это неверно. - person Franci Penov; 16.03.2011
comment
@WhiteFang: это называется хеш-вызовом. - person AbiusX; 16.03.2011
comment
@Franci: вы должны знать компромисс между производительностью и безопасностью. случайные соли добавляют примерно 0,1% безопасности. Хеширование паролей увеличивает безопасность на 90%. Если вы не хэшируете свои пароли, к вашему сайту не присоединится ни один человек, знающий о безопасности. Если вы не посолите их наугад, никого не волнует. Вам нужно сгенерировать радужную таблицу (что в лучшем случае займет месяцы), чтобы взломать постоянный соленый проход. Вам нужно потратить меньше минуты, чтобы взломать проход без хеширования. Вы всегда можете использовать аппаратные токены и биометрию для аутентификации и добавить больше секунды, почему бы вам тогда этого не сделать? - person AbiusX; 16.03.2011
comment
@AbiusX - да, всегда есть компромисс между производительностью и безопасностью. и надлежащая оценка рисков по сравнению с затратами на смягчение последствий должна выполняться каждый раз, когда кто-то решает, какой уровень безопасности им нужен. тем не менее, чего никогда не следует делать, так это просто отвергать меры безопасности и объявлять человека, который их предложил, неправым. По крайней мере, вы могли бы потрудиться спросить ОП, насколько важны данные, стоящие за этим веб-сайтом. также может быть, что жетон hw или биометрические данные являются для них подходящим уровнем. - person Franci Penov; 16.03.2011
comment
@AbiusX - примечание - да, некоторые из наших веб-сайтов используют двухфакторную аутентификацию, при этом токен hw является одним из факторов. и да, это правильный уровень безопасности, учитывая данные, доступные через них. - person Franci Penov; 16.03.2011
comment
@AbiusX - да, это тоже правда. это ваш вопрос, как вы хотите тратить свои усилия. это по-прежнему не делает @Andrew ошибочным в своем предположении, что использование соли для каждого пароля обеспечивает большую безопасность, чем использование одной длинной соли для всех паролей. - person Franci Penov; 16.03.2011
comment
что соль должна быть другой, но постоянной строкой для каждого хешируемого пароля. это @Andrew, а не предложение! - person AbiusX; 17.03.2011
comment
@AbiusX: Вы процитировали Кена Редлера, а не меня. Кроме того, радужные таблицы в современном мире, где вычислительные мощности могут быть сданы в аренду по невысокой цене, не требуют месяцев для компиляции при правильном параллельном использовании. Просто возьмите в аренду несколько экземпляров EC2, и вы получите радужную таблицу, скомпилированную за несколько дней, за несколько долларов, если алгоритм хеширования будет быстрым (семейство sha). Использование каждого пароля по отдельности не увеличивает ваши затраты, не снижает производительности приложений, не увеличивает сложность для пользователей ... Таким образом, это повышает вашу безопасность без каких-либо компромиссов. - person Andrew Moore; 17.03.2011
comment
@Andrew: для правильной реализации требуется гораздо больше кода, и, кстати, вы должны знать о компромиссе с памятью времени Меркла. Чтобы сгенерировать рабочую радужную таблицу для SHA-512 даже с суперкомпьютерами, вам потребуются месяцы. - person AbiusX; 17.03.2011
comment
@AbiusX: Верно, потому что создание случайной строки, объединение ее с хешем и подстрока во время проверки недоступны большинству людей. И да, в одном потоке на это потребуются месяцы. Однако многопоточность и дешевые облачные вычисления приводят к снижению этого числа. Мне нечего добавить к этому разговору. Вы явно настроены по-своему. Это твоя прерогатива. - person Andrew Moore; 17.03.2011
comment
@ Андрей: Мне очень жаль, что я перепутал с тобой @Ken. И я могу показаться оскорбительным, когда это не так, так что еще раз прошу прощения за это. - person AbiusX; 17.03.2011

bcrypt - надежный алгоритм хеширования паролей. Он был создан профессионалами в области безопасности с учетом требований безопасности.

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

Реализация bcrypt для Java доступна по адресу jBCrypt.

person Andrew Moore    schedule 16.03.2011

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

1- Большинство атак происходит, когда вы передаете учетные данные по проводам. (Человек посередине). Поэтому вам нужно убедиться, что передача имени пользователя и пароля должна быть безопасной. (SSL или HTTP-дайджест). Если безопасность очень важна, вам следует изучить, нужно ли вообще передавать имя пользователя / пароль. (с использованием аутентификации на основе токенов, например Oauth, вместо имени пользователя и пароля)

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

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

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

1- Нужно ли вам отправлять имя пользователя / пароль?

2- Можете ли вы убедиться, что пароль нельзя перехватить по сети?

3- Можете ли вы делегировать свою аутентификацию на передний фильтр, а не на уровень вашего приложения?

person uncaught_exceptions    schedule 16.03.2011
comment
Боюсь, что я немного отвлекся. Но простой ответ - не сохраняйте пароль в своем хранилище rdbms. делегируйте это переднему фильтру. (в случае Java-сервера приложений jaas или какой-либо библиотеки, такой как весенняя безопасность, поддерживаемая магазином, например ldap) - person uncaught_exceptions; 16.03.2011