Можно ли заменить рандомизированные соли на пользователя итеративным хешированием? - PullRequest
3 голосов
/ 29 апреля 2010

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

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

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

salt = random();
hashedPassword = hash(salt . password);
storeUserRecord(username, hashedPassword, salt);

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

salt = hash(username);
hashedPassword = hash(salt . password);
storeUserRecord(username, hashedPassword);

(Конечно, hash в приведенных выше примерах должно быть чем-то разумным, например, SHA-512 или каким-то другим сильным хэшем.)

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

РЕДАКТИРОВАТЬ Некоторые, кажется, не понимают, что вопрос. Я ни в коем случае не предлагаю использовать соль. Ссылаясь на отредактированный ответ TheRook: я знаком со ссылками, отмеченными в этих CWE. Основной вопрос, который у меня возникает: почему хеш (имя пользователя) является предсказуемой солью?

РЕДАКТИРОВАТЬ 2 Спасибо всем, кто предоставил ответы; biffabacon прямо обратился к моему основному вопросу в своем 2-м абзаце (в основном, все, что вы можете сделать, чтобы максимизировать область использования солей и, следовательно, генерируемых хешированных паролей, хорошо), но в различных комментариях по этому вопросу есть много полезной информации.

Ответы [ 6 ]

7 голосов
/ 29 апреля 2010

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

Не пытайтесь превзойти соль. Если вы завладеете пространством, не используйте их и приложите все усилия для защиты ваших данных (и резервных копий!) Напрямую.

6 голосов
/ 29 апреля 2010

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

Сравнение атаки с предварительным вычислением против хеш-соли (имени пользователя) и случайной соли: скажем, например, злоумышленник решает создать словари для наиболее распространенных 1000 имен пользователей и, скажем, полдюжины различных хеш-ключей; это 6000 солей и так 6000 словарей. Если используется случайная 32-битная соль, то это 2 ^ 32 или около 4,2 миллиардов словарей. Поэтому, когда соленое пространство резко сокращается (как это происходит с использованием хэша (имени пользователя)), предварительно вычисленные атаки становятся гораздо более осуществимыми

5 голосов
/ 29 апреля 2010

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

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

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

Использование имени пользователя (или его хеша) в качестве соли усиливает уникальность имени пользователя: обычно в данной системе в данный момент времени , имена пользователей являются уникальными. Это предотвращает локальное совместное использование пространства: если злоумышленник получает снимок всех хешированных паролей, он не может атаковать их параллельно с разделением затрат; ему придется понести стоимость хешированного словаря для каждого атакованного пароля. Однако это не препятствует распределению по времени (злоумышленник предварительно вычисляет хешированный словарь с солью, соответствующей пользователю «bob», и будет регулярно пытаться угадать пароль Боба, предполагая, что Боб регулярно меняет свой пароль, например, потому что это поручено его системным администратором). Это не мешает некоторому глобальному совместному доступу (есть несколько - много - систем, где пользователь работает под именем «bob»).

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

1 голос
/ 02 июля 2010

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

Соль должна генерироваться с использованием большого криптографически безопасного псевдослучайного числа . Это число должно быть base256. Хорошим размером будет то же число бит, которое генерирует дайджест сообщения. Например, SHA256 должен иметь 256-битную соль. Оба должны иметь одинаковое количество энтропии, потому что они оба подвержены грубой силе.

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

Почему бы не использовать хэш имени пользователя как соль?

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

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

1 голос
/ 30 апреля 2010

Если вы используете случайную соль, вы получаете очень большой случайный пул возможностей. Когда вы извлекаете имена пользователей, вы вытягиваете из ниоткуда столь большой пул, так как имена пользователей обычно бывают строчными, словарь-слово и являются предметом ограничений, которые ОС / система аутентификации накладывает на имена пользователей. (должен начинаться с буквы, без специальных символов, в некоторых ОС по-прежнему требуется до 8 символов имени пользователя). Многие имена пользователей стандартизированы или, по крайней мере, популярны: root, administrator, bob, mary ... Вы понимаете. Другая проблема состоит в том, что имена пользователей обычно не защищены, вы можете видеть их в пользовательских каталогах apache, анонимный ftp часто позволяет общему каталогу группировать вещи по имени пользователя и т. Д. Злоумышленник может просто начать с сбора имен пользователей и создания себя. очень хороший список солей.

Все эти вещи составляют одну проблему: более высокая вероятность составления списка солей, который работает.

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

0 голосов
/ 29 апреля 2010

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

Вы можете расширить это с помощью нескольких хешей. То есть не просто используйте

  H(password.username.appsalt)

используйте что-то вроде

  h1 = H(password.appsalt1.username.password)
  h2 = H(password.appsalt2.username.password)
  h3 = H(password.appsalt3.username.password)
  H(h1.H(h2.H(h3))))

(где H () - хеш, а '. - простая конкатенация.) Дополнительное время не окажет заметного влияния на ваше приложение, но значительно увеличит стоимость для злоумышленника.

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

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