Неслучайная соль для хэшей паролей

89

ОБНОВЛЕНИЕ: я недавно узнал из этого вопроса, что во всем приведенном ниже обсуждении я (и я уверен, что другие тоже) был немного сбит с толку: то, что я продолжаю называть радужной таблицей, на самом деле называется хеш-таблицей. Радужные таблицы - более сложные существа, и на самом деле они являются разновидностью хеш-цепочек Хеллмана. Хотя я считаю, что ответ все тот же (поскольку он не сводится к криптоанализу), некоторые из обсуждений могут быть немного искажены.
Вопрос: « Что такое радужные таблицы и как они используются? »


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

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


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


Спасибо всем за ответы, но я хотел бы сосредоточиться на областях, с которыми я (немного) менее знаком. В основном это последствия для криптоанализа - я был бы очень признателен, если бы у кого-нибудь был какой-то вклад в крипто-математический PoV.
Кроме того, если есть дополнительные векторы, которые не были учтены, это тоже отличный вклад (см. Пункт @Dave Sherohman о нескольких системах).
Кроме того, если у вас есть теория, идея или передовой опыт - пожалуйста, подкрепите это доказательствами, сценарием атаки или эмпирическими данными. Или даже обоснованные соображения относительно приемлемых компромиссов ... Я знаком с передовой практикой (заглавная буква B, заглавная P) по этому вопросу, я хотел бы доказать, какую ценность это действительно дает.


РЕДАКТИРОВАТЬ: здесь есть действительно хорошие ответы, но я думаю, как говорит @Dave, все сводится к Rainbow Tables для общих имен пользователей ... и, возможно, менее распространенных имен тоже. Однако что, если мои имена пользователей глобально уникальны? Не обязательно уникальный для моей системы, но для каждого пользователя - например, адрес электронной почты.
Не будет никакого стимула создавать RT для одного пользователя (как подчеркнул @Dave, соль не держится в секрете), и это все равно предотвратит кластеризацию. Единственная проблема заключается в том, что у меня могут быть такие же адрес электронной почты и пароль на другом сайте, но соль в любом случае не предотвратит этого.
Итак, мы возвращаемся к криптоанализу - нужна ли энтропия или нет? (Сейчас я считаю, что это необязательно с точки зрения криптоанализа, а по другим практическим причинам.)

AviD
источник
Я должен сказать, что меня смущают многие ответы ниже. Основная цель использования соли - просто предотвратить атаку радужной таблицы, поэтому все, что уникально для пользователя, должно делать, поскольку это заставляет атакующего воссоздавать радужную таблицу для каждой соли. мой 2c.
Горан,
Если соль необходима, например. site, у вас часто есть идентификаторы в URL-адресах. Если злоумышленник знает (а мы предполагаем, что он знает), что соль пароля - это идентификатор пользователя + имя пользователя, довольно легко изменить атаку, чтобы избежать значения соли.
dmajkic
@dmajkic, соль предназначена для предотвращения атак RT и различения одинаковых паролей для разных пользователей. Это данность, даже с именами пользователей.
AviD
@AviD: Это правда. Но если я знаю свой хеш для своего прохода, и я знаю, что соль - это мое имя пользователя, тогда я могу легко создать хешированное значение прохода для любого словарного слова и сравнить его с другим хешем передачи. Поэтому время лучше, чем имя пользователя.
dmajkic
1
Только что нашел статью на веб-сайте Консорциума безопасности PHP, которая в своем примере использует хешированное случайное число md5 в качестве соли phpsec.org/articles/2005/password-hashing.html
helloworlder

Ответы:

156

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

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

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

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

Отредактировано для добавления: многие люди говорят об энтропии и важности энтропии в соли. Это так, но не по той причине, что большинство комментариев на это, кажется, думают.

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

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

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

Дэйв Шерохман
источник
Согласовано. Я бы сделал больший упор на повторное использование имен пользователей, так как я думаю, что атака, скорее всего, будет успешной против гипотетических систем, использующих имя пользователя в качестве соли, которая не удалась бы против системы, использующей случайную соль.
Стив Джессоп,
Я ценю ваше мнение о межсистемной безопасности. Кроме того, я предполагаю, что в будущем не исключено
появление
@AviD: Ты так думаешь? Это довольно специфический вектор атаки.
Дэвид Грант,
2
Не для производства солей, нет. Единственные атаки, на которые влияет соль, - это атаки, направленные непосредственно против хешированных паролей. Атака не может совершить такого рода атаку, если у нее нет копии вашей базы данных паролей, которая также будет содержать соли. Поскольку у злоумышленника уже есть соли в своем распоряжении, им требуется только достаточная энтропия, чтобы избежать хеширования нескольких паролей с одной и той же солью, которую предоставит любой базовый (P) RNG.
Дэйв Шерохман,
3
@ acidzombie24: Использование единственной фиксированной соли (обычно называемой "nonce" в моем опыте) для всех паролей менее безопасно, чем использование уникальной случайной соли для каждого пароля, поскольку это все же позволяет злоумышленнику тривиально определить, имеют ли две или более учетные записи общие тот же пароль. С другой стороны, nonce, скорее всего, будет храниться в вашем коде, а не в базе данных, поэтому злоумышленник, у которого есть только ваша база данных, не получит к ней доступа; из-за этого наиболее безопасным вариантом является использование как общесистемного одноразового номера (хранящегося в коде), так и соли для каждого пароля (хранящегося в базе данных).
Дэйв Шерохман 08
29

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

Возьмите мое имя пользователя "gs" и добавьте его к моему паролю "MyPassword" дает gsMyPassword. Это легко сломать, используя радужную таблицу, потому что, если имя пользователя не имеет достаточной энтропии, это может быть то, что это значение уже хранится в радужной таблице, особенно если имя пользователя короткое.

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

Раньше у них была 12-битная соль . 12 бит - это 4096 различных комбинаций. Это было недостаточно безопасно, потому что сегодня такой объем информации можно легко сохранить . То же самое относится к 4096 наиболее часто используемым именам пользователей. Скорее всего, некоторые из ваших пользователей выберут имя пользователя, которое принадлежит наиболее распространенным именам пользователей.

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

Георг Шёлли
источник
+1 за хороший момент, однако, будет говорить о потенциально массивном столе радуги. Чтобы скрыть все значения длины gsMyPassword (предполагая буквенно-цифровые символы в смешанном регистре), требуется 36 ^ 12 строк в таблице!
Дэвид Грант,
В качестве продолжения: проект распределенной радужной таблицы имеет 63 970 взломанных хэшей, но 36 ^ 12 - это 4 738 381 338 321 616 896!
Дэвид Грант,
Спасибо, и в этом есть смысл, но, как указал мистер PotatoHead, вы все еще расширяете свое пространство за пределы разумной возможности взлома с помощью RT. Кроме того, если мои имена пользователей состоят как минимум из 6-8 символов - какое дополнительное необходимое значение дает энтропия?
AviD
@Potato: вы предполагаете, что радужная таблица содержит все возможные комбинации буквенно-цифровых символов. Это не обязательно, эффективная радужная таблица будет содержать хеши для общих паролей / хешей. Соль существует для защиты от атак по словарю или от комбинированной таблицы и словаря.
Гийом
3
Использование имени пользователя в качестве соли также является плохой идеей для систем, где есть предсказуемо названная учетная запись с высокими привилегиями: «Администратор» в Windows, «root» в * nix, «sa» в MSSQL и т. Д.
никто
8

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

хэш-функция ("www.yourpage.com /" + имя пользователя + "/" + пароль)

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

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

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

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

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

Teedyay
источник
Мне нравится идея привязать пароль к пользователю. Но если злоумышленник может изменить пароль, он наверняка также может изменить идентификатор.
Георг Шелли,
Зависит от идентификатора: я использую первичный ключ таблицы, который вы не можете изменить по своему желанию. ТБХ, если хакер пишет в вашу базу данных, у вас уже довольно большие проблемы ...
teedyay
3
Нет, мне это нравится. Злоумышленник часто является «инсайдером». Я мог бы придумать сценарии, в которых то, что ему нужно, отсутствует в базе данных, но если он может перезаписать учетные данные в базе данных, он сможет аутентифицировать себя, чтобы делать то, что он хочет.
erickson
1
Хорошая точка зрения. Мы действительно обнаруживаем, что становится все труднее добавлять первого пользователя в новую базу данных: мы фактически сделали наши приложения настолько безопасными, что мы едва ли можем взломать их сами. [Кроме того, используйте специальную соль приложения, чтобы вы не могли копировать учетные данные из одной базы данных в другую.]
teedyay
Наконец, я нашел, что кто-то говорит вот что: добавить в соль что-то специфическое для пользователя. Это предотвращает копирование злоумышленником некоторых учетных данных другому пользователю, а также не позволяет хакеру угадать любой пароль, если ему удастся добраться до вашего поля хэша и соли в таблице. Мне нравится еще кое-что: не использовать круглое количество итераций при хешировании. Не берите 10 тысяч или 20 тысяч, а лучше, например, 19835.
Эндрю
3

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

Использование уникальных солей увеличивает сложность массовых словарных атак.

Идеально было бы иметь уникальное криптографически сильное значение соли.

HUAGHAGUAH
источник
2
Вся суть радужной таблицы в том, что значения заранее сгенерированы, и если вы создаете таблицу для значения (например, пароля) ПЛЮС заданной константы, это совершенно другая таблица, и вы можете просто попробуйте результат хеширования напрямую. :)
Дэвид Грант
1
Постоянный хеш ничего не стоит. Все пароли можно взломать с помощью единой радужной таблицы. Соль предназначена для того, чтобы создать радужный стол невозможно.
Георг Шелли,
1
@gs - Я не понимаю, почему вы не можете построить радужную таблицу, которая «включает» эффекты постоянной соли. Пространство атаки (пароль) не изменится, поэтому таблицу не нужно будет увеличивать, ее нужно будет просто пересчитать.
HUAGHAGUAH
@ Картофель - зависит от компромисса. Если 20 тысяч логинов вашей компании были хешированы с одной и той же постоянной солью, может быть дешевле вычислить новую радужную таблицу, чем атаковать их по словарю по отдельности. Отсюда мой акцент на «НАБОР».
HUAGHAGUAH
3

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

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

Кибби
источник
3
«Суть в том, что вы не можете использовать стандартную радужную таблицу для решения каждого пароля в базе данных». Я не согласен. Дело в том, что вы не можете использовать стандартную радужную таблицу для решения любого пароля. Если соль - это имя пользователя, то радужная таблица для "root" может взломать pw root.
Стив Джессоп,
Это, наверное, единственное правило, которое действительно имеет значение. По сути, вы хотите, чтобы пароль был уникальным для вашей системы, но это не имеет значения. Хотя это может быть что-то простое. Вам не нужно много энтропии.
Kibbee
Я тоже так думал - но застрял на «наверное, хорошо». Я до сих пор не вижу, чтобы эта теория была доказана - или, по крайней мере, подтверждена, что нет никаких последствий для криптоанализа.
AviD
@onebyone: если соль состоит из имени пользователя + постоянного локального значения (я часто использую ':'), то это все равно разрушает стандартизированные RT, если только не существует их множества, которые включают общие имена пользователей и обычные статические значения соли. Я подозреваю, что это не так.
nsayer
Наряду с nsayer. Вы можете использовать общесистемную постоянную строку, для которой не было бы предварительно сгенерированного RT, например # (D83d8, вместе с именем пользователя в качестве соли, и это, вероятно, предотвратило бы любые атаки на радужную таблицу.
Кибби,
3

Сила хэш-функции не определяется ее вводом!

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

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

Изменение соли каждый раз, когда пользователь меняет свой пароль, может помочь отразить продолжительные атаки, равно как и применение разумной политики паролей, например, смешанный регистр, пунктуация, минимальная длина, изменение через n недель.

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

Дэвида Гранта
источник
Сила функции не меняется, но вывод определенно меняется. Если на вход можно повлиять или он известен, то, возможно, можно будет сделать вывод о хэш-значении. Это риск.
Мартин Карпентер,
@Martin: Единственное, что вы можете определить из хеш-значения, есть ли у вас совпадение! Ввод «roota» или «rootb» (где «a» и «b» представляют пароль) в хеш-функцию даст вам радикально другой результат.
Дэвид Грант,
Соли известны злоумышленнику с помощью радужных таблиц.
Георг Шелли,
Сервер должен знать незашифрованную соль (чтобы проверить пароль по хешу), поэтому можно считать само собой разумеющимся, что злоумышленник имеет доступ к соли или может получить ее очень легко.
Георг Шелли,
Верно, верно, это данность - чтобы быть более конкретным, я имел в виду силу всей криптосистемы (или -подсистемы по отношению к хешам).
AviD
1

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

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

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

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

CraigTP
источник
Опять же, я не имею в виду использование одной постоянной соли - скорее, неслучайное, но уникальное для пользователя значение. Например, userId.
AviD
Все дело в том, что ваша соль никогда не должна быть постоянной. Каждая вещь, которую вы хешируете, независимо от того, одно и то же «входное» значение или нет, должна иметь разную соль. Дэйв Шерохман объясняет недостатки использования даже уникальных для пользователя значений, которые, по сути, остаются неизменными при каждом вычислении хэша.
CraigTP
-1

Энтропия - это точка значения соли.

Если за солью стоит какая-то простая и воспроизводимая «математика», то это то же самое, что и соль не там. Просто добавление стоимости времени должно быть нормальным.

dmajkic
источник
Я не понимаю этого комментария. Вы говорите «использовать энтропию», а затем: «использовать время» ??
Мартин Карпентер,
если имя пользователя используется для соли, это недостаточно энтропийно. Но если вы используете имя пользователя + текущую дату и дату - это так, так как сложно угадать, когда именно была создана соль.
dmajkic
«достаточно энтропийный» - субъективно; это ваш стандарт. Своевременное обоснование этого значения может оказаться недостаточным.
Мартин Карпентер,
Не существует такой вещи, как «абсолютная истинная случайность». Мы должны сказать, когда он «достаточно хорош». Если вы думаете, что в этом случае времени недостаточно, используйте что-нибудь другое. stackoverflow.com/questions/84556/…
dmajkic
На самом деле, суть проблемы состоит в том, чтобы сделать каждый результат хеширования уникальным - чтобы предотвратить (а) атаки на радужную таблицу и (б) идентичную идентификацию пароля. Вопрос в том, для чего еще нужна энтропия, если вообще нужна?
AviD