Где вы храните свои соленые струны?

250

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

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

С точки зрения безопасности, стоит ли хранить соли в другом месте? Рассмотрим веб-приложение с кодом сервера и БД на одном компьютере. Если соли хранятся в плоском файле на этом компьютере, есть вероятность, что, если база данных скомпрометирована, файл солей тоже будет.

Есть ли рекомендуемые решения для этого?

friedo
источник
9
Если есть место, где вы можете хранить соль, в которую злоумышленник не может попасть, тогда вам следует просто хранить там пароли. Но почему бы не использовать разные соли для каждого пароля?
jrockway
8
Он использует разные соли для каждого пароля, jrockway.
Amber
9
Насколько велики ваши соли? Ваши соли должны быть достаточно большими (32 бита?), Чтобы практически не было шансов, что для них был заранее рассчитан радужный стол.
М. Дадли
@emddudley В эти дни я привык использовать 64-битное целое число в качестве соли, но нет причин, по которым я не могу сделать их длиннее.
Фридо
10
Автор PWDTK здесь sourceforge.net/projects/pwdtknet , честно говоря, я бы не волновался, и я бы просто хранил соль в той же БД, что и пароль. В любом случае вы должны всегда предполагать, что соль известна злоумышленнику, поэтому вам следует сосредоточиться на использовании КРУПНОЙ СЛУЧАЙНОЙ соли и выполнении достаточного растяжения ключа (итерации в PBKDF2), так что создание даже одной радужной таблицы для одной известной соли невозможно. Честно говоря, то, чего вы пытаетесь достичь, помещая соль в другое место, - это «Безопасность от неизвестности» и, как правило, не приносит никакой пользы, когда вы смотрите на такие вещи, как другой сервер, который потенциально может выйти из строя.
thashiznets

Ответы:

259

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

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

янтарный
источник
17
Согласовано. Модель угрозы, от которой вы защищаете, храня соль отдельно, - это пользователь, который может каким-то образом получить доступ к соли в БД с помощью недостойных средств, но не с помощью хэша (в БД). И что этот человек начнет вычислять радужную таблицу заранее, предполагая, что сможет найти хэш позже. Не невозможно, но и не стоит инженерных усилий для защиты против этой единственной авеню атаки.
Том Риттер
Хороший пост, мне было интересно то же самое. Я никогда не думал о соли на пользователя, я думал, что одна соль будет работать для всех пользователей. Как насчет соли, которая хранится в виде XML-файла, который загружается сервером приложений? или может быть как-то жестко закодирован в сервлет?
Джигзат
9
@Jigzat - Солить бессмысленно, если у вас нет отдельной соли для каждого пользователя. Соль в том, чтобы сделать взлом хешей отдельной задачей для каждого пароля пользователя; если соль одинакова для всех из них, то это не так.
Янтарь
3
@TomRitter это не единственный случай. вы предполагаете, что все пароли сложны. некоторые злоумышленники могут взять соль и хэш и проверить только 10 000 самых распространенных паролей. таким образом они получат приличное количество людей. однако, если они не имеют доступа к соли, это похоже на то, что у пользователя более длинный и более безопасный пароль. Теперь, насколько вероятно, что соленая база данных останется в безопасности, пока база данных паролей будет украдена, для обсуждения, но это отдельная проблема.
chacham15
@ Янтарь, я верю, что ТомРиттер прав. Хранение соли отдельно означает разницу между принуждением атакующего использовать атаку грубой силой и более легкой атакой по словарю. Если вы знаете соль, вы можете просто добавить ее во время запуска словарной атаки. Если вы можете на 100% защитить свою соль, вы можете просто использовать ту же соль и заставить злоумышленников перебить все (даже для пользователей, которые используют «пароль» в качестве пароля). Но можете ли вы защитить свою соль .... вероятно, нет. Таким образом, можно также уменьшить количество точек отказа, храня их рядом с хешем, и применять более строгие правила паролей.
Ультратрунки
35

Я предоставлю немного другой взгляд на это.

Я всегда храню соль, смешанную с хешем соли-пароля.

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

Мое обоснование для этого подхода:

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

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

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

Вывод к этому ..

1) Никогда не храните данные, которые ваше приложение аутентификации использует в точном виде.

2) Если возможно, держите свою логику аутентификации в секрете для дополнительной безопасности.

Иди на шаг дальше ..

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

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

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

При аутентификации ввода пароля пользователя ваше приложение передаст строку и предположит, что первый 1 байт данных - это первый 1 байт соли, за которым следует хеш-код соли. Этот проход не удастся. Приложение будет продолжено с использованием первых 2 байтов данных в качестве первых 2 байтов соли и повторяется до тех пор, пока не будет найден положительный результат после использования первых 200 байтов в качестве первых 200 байтов соли. Если пароль неверный, приложение продолжит пробовать все перестановки, пока они не будут найдены.

Плюсы этого подхода:

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

Минусы этого подхода:

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

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

Этот подход может быть реализован различными способами и может быть сделан еще более безопасным с использованием солей переменной ширины и / или хешей с солеными паролями.

Ibraheem
источник
9
С вашим подходом вы просто добавляете секрет в свой процесс хеширования (алгоритм, который применяет соль). Этот секрет вы можете добавить намного проще, добавив перец к соли, я попытался указать это в моем уроке . Современные хеш-функции, такие как BCrypt, будут применять соль самостоятельно, используя исходную соль в каждой итерации, так что вы все равно не сможете ее контролировать.
martinstoeckli
@martinstoeckli Хотя вы и правы, что BCrypt применяет соль самостоятельно, хранение этого хеша соль + зависит только от вас, как от разработчика. Таким образом, вы можете легко добавить перец в соль + хеш и сохранить его в базе данных. Затем при последующем извлечении вы читаете значение из базы данных, удаляете значение перца и передаете оставшееся значение в BCrypt.
PeterToTheThird
2
@PeterToTheThird - это сведет на нет преимущество перца. Перец добавляет секрет на стороне сервера и работает только до тех пор, пока он остается секретным (напротив соли). Типичная атака - SQL-инъекция, когда кто-то получает доступ к базе данных, но не к коду, перец, хранящийся в базе данных, будет бесполезен. Большинство реализаций BCrypt автоматически добавляют соль к результирующему хеш-значению, поэтому это значение уже содержит соль, коэффициент стоимости, алгоритм и хеш. Эта строка может храниться в одном поле длиной 60 символов.
martinstoeckli
Чтобы добавить, что при использовании функции «усиления ключа», такой как BCrypt, вы не можете контролировать использование соли. Однако, если вы хотите использовать перец, вы просто добавляете перец к соли и используете его как «соль с перцем» вместо «соли», вводимой в функцию хеширования. «Перец» тогда представляет собой подходящий кусок данных, который не хранится в базе данных, но встраивается в код аутентификации или хранится в другом безопасном месте. Я подошел к проблеме с общей точки зрения, используя SHA-512 в качестве примера функции, но BCrypt и т. Д. Также можно использовать аналогичным образом.
Ибрагим
2
@martinstoeckli - да, фактическая реализация зависит от того, какую хеш-функцию вы используете. Очевидно, что вам нужно учитывать параметры и выходные данные хеш-функции при реализации вашей логики аутентификации. В конечном счете, перец - это еще одна переменная, введенная в вашу функцию хеширования, которая не хранится в том же месте, что и соль и хеш.
Ибрагим
23

Часто они добавляются к хешу и сохраняются в одном поле.

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

Если бы у вас было более безопасное хранилище, то было бы разумно просто хранить там хэши.

никто
источник
4
Но что произойдет, если все хешированные пароли будут пропущены, включая их соответствующие соли? Разве это не так небезопасно?
mghaoui
10
@mghaoui Но тогда, если вы хотите узнать «пароль», вам все равно придется составить Радужную Таблицу для каждой соли, если только некоторые соли не совпадают.
Франклин
4

На основе книги по разработке веб-приложений ASP.NET MVC 4 Уильяма Пенберти:

  1. Получение доступа к солям, хранящимся в отдельной базе данных, требует от хакеров взлома двух разных баз данных, чтобы получить доступ к соли и паролю с солью. Хранение их в той же таблице, что и пароль, или даже в другой таблице той же базы данных будет означать, что, когда хакеры получат доступ к базе данных, они получат доступ как к соли, так и к паролю. Поскольку безопасность включает в себя процесс создания взлома системы слишком дорогим или длительным, чтобы того стоить, удвоение количества доступа, которое хакер должен получить, должно сделать систему более безопасной.
  2. Простота использования является основной причиной хранения солей в той же базе данных, что и хешированные пароли. Вам не нужно было бы гарантировать, что две базы данных всегда доступны одновременно и всегда синхронизированы. Преимущество наличия соли минимально, если у каждого пользователя есть рандомизированная соль, потому что, хотя это может упростить обнаружение пароля индивидуума, количество силы, необходимой для взлома паролей системы в целом, будет высоким. На этом уровне обсуждения именно этого и ожидают: защитить пароли. Если хакеры получили копию базы данных, данные вашего приложения уже скомпрометированы. На данный момент проблема заключается в том, чтобы снизить риски пользователей из-за возможности использования общих паролей.
  3. Требование поддержания двух отдельных связанных баз данных является обширным. Конечно, он добавляет восприятие безопасности, но единственное преимущество, которое он дает, - это то, что он защищает пароль, единственный элемент данных. Если бы каждое поле в базе данных было индивидуально зашифровано, и для этого использовалась та же самая соль, было бы более целесообразно хранить его отдельно от данных, поскольку повышена базовая безопасность вашей системы.
ДАНЕШ
источник
Если приложение может аутентифицироваться в обеих базах данных, разве это не по сути то же самое, что если бы это была одна база данных, если злоумышленник скомпрометировал код приложения?
Джон Эрнест
0

Соль в том, чтобы сделать все радужные столы бесполезными и потребовать создания нового набора из них. Чтобы угадать строку нужно столько же времени, сколько и для создания радуги. Например, SHA-256 хэш "пароль" есть 5e88 4898 da28 0471 51d0 e56f 8dc6 2927 7360 3d0d 6aab bdd6 2a11 ef72 1d15 42d8. После добавления соли, такой как «badpassword», новой хэшируемой строкой будет «passwordbadpassword», который из-за лавинообразного эффекта резко меняет вывод на 457b f8b5 37f1 802e f9c8 2e46 b8d3 f8b5 721b 7cbb d485 f0bb e523 bfbe 73e6 58d6.

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

Эрик Джин
источник