Необходимость сокрытия соли для хеша
На работе у нас есть две конкурирующие теории для солей. Продукты, над которыми я работаю, используют что-то вроде имени пользователя или номера телефона, чтобы засолить хэш. По сути, то, что отличается для каждого пользователя, но легко доступно для нас. Другой продукт случайным образом генерирует соль для каждого пользователя и меняется каждый раз, когда пользователь меняет пароль. Затем соль зашифровывается в базе данных.
Мой вопрос: действительно ли необходим второй подход? Я могу понять с чисто теоретической точки зрения, что это более безопасно, чем первый подход, но как насчет с практической точки зрения. Прямо сейчас, чтобы аутентифицировать пользователя, соль должна быть незашифрована и применена к информации для входа.
Подумав об этом, я просто не вижу реальной выгоды от такого подхода. Изменение соли с учетной записи на учетную запись по-прежнему крайне затрудняет попытку грубого форсирования алгоритма хеширования, даже если злоумышленник знал, как быстро определить, какой он был для каждой учетной записи. Это происходит при условии, что пароли достаточно надежны. (Очевидно, что найти правильный хеш для набора паролей, где все они состоят из двух цифр, значительно проще, чем найти правильный хеш паролей, который состоит из 8 цифр). Я ошибаюсь в своей логике или мне чего-то не хватает?
РЕДАКТИРОВАТЬ: Хорошо, вот причина, почему я думаю, что это действительно спорный для шифрования соли. (дай мне знать, если я на правильном пути).
Для следующего объяснения мы будем предполагать, что пароли всегда состоят из 8 символов, а соль - 5, а все пароли состоят из строчных букв (это просто упрощает математику).
Наличие разной соли для каждой записи означает, что я не могу использовать одну и ту же радужную таблицу (на самом деле технически я мог бы, если бы у меня был достаточный размер, но давайте пока проигнорируем это). Это реальный ключ к соли из того, что я понимаю, потому что, чтобы взломать каждый аккаунт, я должен заново изобрести колесо, так сказать для каждого. Теперь, если я знаю, как применить правильную соль к паролю для генерации хеша, я бы сделал это, потому что соль действительно просто увеличивает длину / сложность хешированной фразы. Поэтому я бы сократил число возможных комбинаций, которые мне нужно было бы сгенерировать, чтобы "узнать", что у меня есть пароль + соль с 13^26 до 8^26, потому что я знаю, что такое соль. Теперь это облегчает, но все еще очень сложно.
Так что на шифрование соли. Если бы я знал, что соль зашифрована, я бы не стал сначала пытаться ее расшифровать (если я знаю, что она имеет достаточный уровень шифрования). Я бы проигнорировал это. Вместо того, чтобы пытаться понять, как его расшифровать, возвращаясь к предыдущему примеру, я просто сгенерировал бы большую радужную таблицу, содержащую все ключи для 13^26. Не зная, что соль определенно замедлит меня, но я не думаю, что это добавит монументальную задачу - сначала попытаться взломать шифрование соли. Вот почему я не думаю, что это того стоит. Мысли?
Вот ссылка, описывающая, как долго пароли будут держаться при атаке грубой силы: http://www.lockdown.co.uk/?pg=combi
10 ответов
Ответ здесь заключается в том, чтобы спросить себя, от чего вы действительно пытаетесь защитить? Если у кого-то есть доступ к вашей базе данных, то у него есть доступ к зашифрованным солям, и, вероятно, он также имеет доступ к вашему коду. Со всем этим они могли расшифровать зашифрованные соли? Если так, то шифрование в любом случае бесполезно. Соль действительно в том, чтобы сделать это таким образом, что невозможно создать радужную таблицу, которая взломает всю вашу базу паролей за один раз, если она будет взломана. С этой точки зрения, до тех пор, пока каждая соль уникальна, нет никакой разницы, для ваших паролей или зашифрованных солей потребуется индивидуальная атака методом подбора.
Скрывать соль не нужно.
Разная соль должна использоваться для каждого хэша. На практике этого легко достичь, получая 8 или более байтов от генератора случайных чисел криптографического качества.
Соль помогает предотвратить атаки предварительно рассчитанных словарей.
Предположим, у злоумышленника есть список вероятных паролей. Он может хэшировать каждый и сравнивать его с хешем пароля своей жертвы и проверять, совпадает ли он. Если список большой, это может занять много времени. Он не хочет тратить так много времени на свою следующую цель, поэтому он записывает результат в "словарь", где хеш указывает на соответствующий ввод. Если список паролей очень и очень длинный, он может использовать такие методы, как Rainbow Table, чтобы сэкономить место.
Однако предположим, что его следующая цель засолила свой пароль. Даже если злоумышленник знает, что такое соль, его предварительно вычисленная таблица ничего не стоит - соль меняет хэш, полученный в результате каждого пароля. Он должен повторно хэшировать все пароли в своем списке, прикрепляя соль цели к входным данным. Каждая отдельная соль требует отдельного словаря, и если будет использовано достаточно солей, у злоумышленника не будет места для хранения словарей для всех них. Торговое пространство для экономии времени больше не является опцией; злоумышленник должен вернуться к хешированию каждого пароля в своем списке для каждой цели, которую он хочет атаковать.
Так что не нужно хранить соль в секрете. Достаточно убедиться, что у злоумышленника нет предварительно вычисленного словаря, соответствующего этой конкретной соли.
Подумав об этом немного больше, я понял, что обманывать себя, думая, что соль может быть спрятана, опасно. Гораздо лучше предположить, что соль не может быть спрятана, и спроектировать систему, несмотря на это, безопасно. Я приведу более подробное объяснение в другом ответе.
Скрытая соль больше не является солью. Это перец. Это имеет свое применение. Это отличается от соли.
Pepper - это секретный ключ, добавляемый к паролю + соли, который превращает хэш в HMAC (код аутентификации сообщений на основе хеша). Хакер, имеющий доступ к выводу хеша и соли, теоретически может грубо силой угадать ввод, который сгенерирует хеш (и, следовательно, пройдет проверку в текстовом поле пароля). Добавляя перец, вы увеличиваете проблемное пространство криптографически случайным образом, делая проблему неразрешимой без серьезного оборудования.
Для получения дополнительной информации о перце, проверьте здесь.
Смотрите также hmac.
... что-то вроде имени пользователя или номера телефона, чтобы засолить хеш....
Мой вопрос: действительно ли необходим второй подход? Я могу понять с чисто теоретической точки зрения, что это более безопасно, чем первый подход, но как быть с практической точки зрения?
С практической точки зрения соль - это деталь реализации. Если вы когда-либо измените способ сбора или хранения информации о пользователе - а имена пользователей и номера телефонов иногда меняются, чтобы использовать ваши точные примеры - тогда вы, возможно, поставили под угрозу свою безопасность. Вы хотите, чтобы такое внешнее изменение имело гораздо более глубокие проблемы с безопасностью?
Требует ли отмена требования о том, чтобы у каждой учетной записи был номер телефона, необходимо провести полную проверку безопасности, чтобы убедиться, что вы не открыли эти учетные записи для компрометации безопасности?
Второй подход только немного более безопасен. Соли защищают пользователей от словарных и радужных атак. Они усложняют амбициозному злоумышленнику угрозу для всей вашей системы, но по-прежнему уязвимы для атак, направленных на одного пользователя вашей системы. Если вы используете общедоступную информацию, такую как номер телефона, и злоумышленник узнает об этом, то вы сохранили для них шаг в атаке. Конечно, вопрос спорный, если злоумышленник получит всю вашу базу данных, соли и все.
РЕДАКТИРОВАТЬ: После перечитывания этого ответа и некоторых комментариев мне приходит в голову, что некоторая путаница может быть связана с тем, что я сравниваю только два очень специфических случая, представленных в вопросе: случайная соль против неслучайная соль. Вопрос использования телефонного номера в качестве соли является спорным, если злоумышленник получает всю вашу базу данных, а не вопрос использования соли вообще.
Я понимаю, что "соль" делает взлом более трудным, но он не пытается скрыть лишние данные. Если вы пытаетесь повысить безопасность, делая соль "секретной", то вам просто нужно больше битов в ключах шифрования.
Вот простой пример, показывающий, почему плохо иметь одинаковую соль для каждого хеша
Рассмотрим следующую таблицу
UserId UserName, Password
1 Fred Hash1 = Sha(Salt1+Password1)
2 Ted Hash2 = Sha(Salt2+Password2)
Случай 1, когда соль 1 совпадает с солью 2. Если Hash2 заменен на Hash1, тогда пользователь 2 может войти в систему с паролем пользователя 1
Случай 2, когда соль 1 не совпадает с солью 2 Если Hash2 заменен на Hash1, то пользователь2 не может войти в систему с паролем пользователя 1.
Есть две техники с разными целями:
"Соль" используется для того, чтобы два разных одинаковых пароля шифровались по-разному. Таким образом, злоумышленник не может эффективно использовать атаку по словарю против целого списка зашифрованных паролей.
(Общий) "секрет" добавляется перед хэшированием сообщения, так что злоумышленник не может создавать свои собственные сообщения и принимать их.
Я склонен прятать соль. Я использую 10 бит соли, добавляя случайное число от 1 до 1024 к началу пароля перед его хэшированием. При сравнении пароля, введенного пользователем с хешем, я делаю цикл от 1 до 1024 и пробую каждое возможное значение соли, пока не найду совпадение. Это занимает менее 1/10 секунды. У меня появилась идея сделать это таким образом из PHP password_hash и password_verify. В моем примере, "стоимость" составляет 10 за 10 бит соли. Или из того, что сказал другой пользователь, скрытая "соль" называется "перец". Соль не зашифрована в базе данных. Это грубое вытеснение. Это сделало бы радужный стол необходимым для обращения хеша в 1000 раз больше. Я использую sha256, потому что это быстро, но все еще считается безопасным.
На самом деле, это зависит от того, от какого типа атаки вы пытаетесь защитить свои данные.
Целью уникальной соли для каждого пароля является предотвращение атаки по словарю на всю базу паролей.
Шифрование уникальной соли для каждого пароля усложнит взлом отдельного пароля, да, но вы должны взвесить, есть ли какая-то польза от этого. Если злоумышленник, используя грубую силу, обнаружит, что эта строка:
Marianne2ae85fb5d
хэши к хешу, хранящемуся в БД, неужели так сложно понять, какая часть является проходом, а какая - солью?