Рекомендации: пароли для посола и перца?

145

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

hash_function($salt.hash_function($pepper.$password)) [multiple iterations]

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

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

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

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

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

Глюк Желание
источник
3
Не совсем дубликат, но чрезвычайно связанный: stackoverflow.com/questions/16594613/…
ircmaxell
2
Межсайтовый дубликат: security.stackexchange.com/q/3272/2113
Jacco

Ответы:

306

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

Кажущийся перевернутый перец

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

Вот почему так много людей считают, что перец - хорошая идея. Это имеет смысл".

Реальность перца

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

И перцы не соответствуют ни доказуемым, ни обслуживаемым моделям ...

Теоретические проблемы с перцем

Теперь, когда мы подготовили почву, давайте посмотрим, что не так с перцем.

  • Подача одного хэша в другой может быть опасной.

    В вашем примере вы делаете hash_function($salt . hash_function($pepper . $password)).

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

    Вот почему такие алгоритмы, как PBKDF2, используют специальные операции для их объединения (в этом случае hmac).

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

    Хотя это может показаться чисто теоретическим, на самом деле это не так. Например, Bcrypt не может принимать произвольные пароли . Таким образом, передача bcrypt(hash(pw), salt)может действительно привести к гораздо более слабому хешу, чем bcrypt(pw, salt)если бы hash()возвращает двоичную строку.

  • Работать против дизайна

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

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

    Это не значит, что это небезопасно. Это означает, что мы не знаем, безопасно ли это. И общая рекомендация по безопасности и криптографии: если мы не знаем, это не так.

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

  • Сложность - враг безопасности

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

Значительные проблемы с перцем

  • Это не ремонтопригодно

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

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

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

    Что делает ваш подход незамедлительным.

  • Это требует от вас, чтобы свернуть свой собственный крипто

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

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

    НИКОГДА не катите свой собственный крипто ...

Лучший путь

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

  • Просто используйте алгоритмы, как они существуют

    Если вы используете bcrypt или scrypt правильно (с высокой стоимостью), все пароли словаря, кроме самых слабых, должны быть статистически безопасными. Текущая запись для хеширования bcrypt со стоимостью 5 составляет 71 тыс. Хешей в секунду. При такой скорости даже 6-символьный случайный пароль взламывается годами. А учитывая, что моя минимальная рекомендуемая стоимость равна 10, это уменьшает число хэшей в секунду в 32 раза. Таким образом, мы будем говорить только о 2200 хэшах в секунду. При этом даже некоторые словарные фразы или модификации могут быть безопасными.

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

  • Зашифруйте выходной хэш до хранения

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

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

TL / DR

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

ircmaxell
источник
6
Спасибо, что включили эту последнюю часть шифрования хеш-значения, это ответ, с которым я полностью согласен. Если бы шифрование стало частью вашего пароля api , не было бы никаких причин не использовать его, так что, возможно ... (я хотел бы написать документацию для него)
martinstoeckli
2
@martinstoeckli: Я бы не согласился добавить шаг шифрования в упрощенный API хеширования. Причина в том, что хранение секретов (ключей) намного сложнее, чем думают люди, и довольно легко выстрелить себе в ногу. Для 99,9% пользователей raw bcrypt более чем достаточно для всех, кроме самых простых паролей ...
ircmaxell
7
@ircmaxell - С другой стороны, вы ничего не потеряете. В худшем случае, когда ключ становится известным, злоумышленник все равно должен взломать хеш BCrypt (та же ситуация, что и без шифрования). Это не то же самое, что хранение ключа для шифрования данных, речь идет о добавлении секрета на стороне сервера. Даже жестко закодированный ключ защитит эти слабые пароли, если злоумышленник не имеет контроля над сервером / кодом. Такая ситуация не редкость: помимо SQL-инъекций, также могут быть выброшены резервные копии, удаленные серверы ... Многие пользователи PHP работают на хостинговых серверах.
martinstoeckli
2
@martinstoeckli Я бы согласился с ircmaxwell здесь, я не думаю, что шифрование относится к паролю API. Хотя, можно отметить, что для максимальной безопасности шифрование ваших хэшей является дополнительным условием, которое можно использовать.
Foochow
1
Мне было указано на раздел 2.4.5 стандарта проверки безопасности приложений OWASP 4.0, в котором рекомендуется использовать секретную соль (также известный как перец): «Убедитесь, что выполняется дополнительная итерация функции вывода ключа с использованием секретного значения соли, которое известно только верификатор. »
Майкл
24

Во-первых, мы должны говорить о точном преимуществе перца :

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

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

  • Уникальная соль на пароль
  • Алгоритм медленного хеширования, такой как BCrypt

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

Второй вопрос, как применять перец ?

Часто рекомендуемый способ применить перец - это объединить пароль и перец перед передачей его хэш-функции:

$pepperedPassword = hash_hmac('sha512', $password, $pepper);
$passwordHash = bcrypt($pepperedPassword);

Есть и другой, еще лучший способ:

$passwordHash = bcrypt($password);
$encryptedHash = encrypt($passwordHash, $serverSideKey);

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

martinstoeckli
источник
Итак, вы бы сказали, что перец добавляет безопасности только соли, короче? Спасибо за помощь в том, как реализовать.
Glitch Desire
1
@LightningDust - Да, это так, для слабых паролей, пока перец остается в секрете. Это смягчает некоторые четко определенные типы угроз.
martinstoeckli
@martinstoeckli, безусловно, хороший способ реализовать это. Приятно видеть, что кто-то с некоторым опытом в области безопасности поддерживает этот метод. Будет ли AES_ENCRYPT($passwordHash, $serverSideKey)вызов MySQL также подходящим способом реализации этого?
foochow
1
@Foo_Chow - я не знаю реализацию функции MySQL, но кажется, что они использовали режим EBC, чтобы избежать IV-вектора. Вместе с известным открытым текстом (хеш-значения всегда начинаются с одинаковых символов), это может быть проблемой. На моей домашней странице я опубликовал пример реализации, которая обрабатывает это шифрование.
martinstoeckli
@martinstoeckli интересно, не слишком знаком с понятиями; однако кажется, что IV был бы желателен для самых надежных результатов. Кажется, не добавляет много накладных расходов для дополнительной выгоды.
Foochow
2

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

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

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

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

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

Aron
источник
Так что соль + перец предлагает больше безопасности, чем просто соль? Или мне лучше уронить перец и запустить больше итераций сценария?
Glitch Desire
2
Главное в радужном столе заключается в том, что вы не создаете его для конкретной атаки, вы загружаете уже существующий. Есть длинные радужные таблицы, доступные для популярных алгоритмов хэширования, только в Google!
Ричард
1
@ LightningDust Я не могу думать ни о какой причине сам. Однако Ричард в другой теме придумал одну. Вы можете скрыть перец в своем исходном коде, что означает другое место, к которому ваш злоумышленник должен получить доступ, просто чтобы собрать радужный стол.
Арон
@Aron - Ну вот что я подумал, так как мы серверы приложений отдельно от серверов баз данных (то есть, если вы получите rootна нашем дб сервере, вы по- прежнему не имеют доступа к нашему серверу приложений), что скрытие перец в исходном коде (в наш конфигурационный файл) обеспечит дополнительную безопасность.
Glitch Desire
1

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

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

Sven
источник
1
Это сделало бы предварительно вычисленную радужную таблицу для несоленной таблицы паролей бесполезной. Короче говоря, даже если злоумышленник знает ваш перец, ему нужно будет создать новый радужный стол.
Арон
3
Это усиливает хэш на основе данных, отсутствующих в базе данных, что является хорошей вещью. Вещи в базе данных могут быть потенциально обнаружены в уязвимостях - менее вероятно, что значение в коде будет получено таким же образом.
Ричард
Соли - это односторонние функции, и даже успешное взлом паролей только даст вам этот пароль и не поможет вам получить само значение перца.
Glitch Desire
1
@ LightningDust Я думаю, что вы имеете в виду «Хэши - это функции-ловушки». Да, невозможно определить вашу соль и / или перец из безопасного хэша (фактически это определение безопасного хэша).
Арон
6
@Aron Security Through Obscurity может быть допустимой техникой, используемой в качестве слоя защиты. Дело в том, что на него никогда не следует полагаться в качестве защиты, а вместо этого использовать его для «замедления атакующего». Если бы это было не так, что-то вроде honeypot не использовалось бы. Вместо этого мы можем эффективно использовать безопасность через неясность, чтобы помочь замедлить злоумышленников, если мы не полагаемся на это для безопасности нашего приложения.
ircmaxell