Хранение паролей в безопасности - PullRequest
1 голос
/ 04 августа 2009

Ситуация 1 - подключение сервера к базе данных:
Всегда говорилось, что пароли не должны храниться в виде простого текста, однако для подключения к базе данных mysql требуется пароль, в виде простого текста, кажется ... Я предполагаю, что лучшее решение для этого - хранить его в зашифрованном виде, расшифруйте его в моем приложении по мере необходимости, а затем сотрите из памяти (SecureZeroMemory в Windows, я думаю, компилятор не может его оптимизировать).

Ситуация 2 - пользователи, входящие на сервер с удаленного компьютера:
Что касается паролей пользователей, я планирую никогда вообще не сохранять исходный пароль. Вместо этого я буду хранить случайно сгенерированную "соль", для каждого пользователя, префикс этого пароля, а затем хэш, что, по-видимому, является довольно распространенным способом. Однако на данный момент у меня нет доступного SSL-соединения, поэтому я предполагаю, что пароли в виде простого текста могут быть перехвачены, что является хорошим решением для этого?

Какие хорошие алгоритмы (ссылки на реализации C / C ++ также были бы полезны, если они у вас есть) для этого, при поиске в сети их 100?

EDIT:
Если я получу SSL, будет ли безопасным следующее (при условии, что используется сильный алгоритм хеширования), или следует использовать другой метод?

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

Ответы [ 5 ]

1 голос
/ 26 мая 2010

Ситуация 1 - подключение сервера к базе данных

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

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

Ситуация 2 - пользователи, входящие на сервер с удаленного компьютера

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

Также стоит подумать, должна ли ваша аутентификация работать на основе «что-то, что вы знаете» (пароли) или «что-то, что у вас есть» (открытый / закрытый ключи). Исходя из вашего вопроса, что мы ищем пароли, мне нравятся два: SRP и Kerberos.

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

Мне также нравится Kerberos, потому что он поддерживается тоннами программного обеспечения (я знаю, что Postgres поддерживает его, я только нашел упоминания о mysql, не поддерживающем какую-либо хорошую технологию аутентификации) и имеет систему «билетов», которая обеспечивает единый знак по возможности. Kerberos нужна какая-то другая технология, чтобы усилить свой первоначальный обмен аутентификацией, и SRP был бы хорош для этого, но я не уверен, что они это уже сделали. Я думаю, что-то в этом делает KDC (сервер ключей) с состоянием.

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

Приятно то, что, как только вы установили строгий обмен аутентификацией, другие хорошие вещи обычно выпадают из него бесплатно. В итоге обе стороны делятся общим «секретом», который можно использовать один раз в течение сеанса, никогда не отправлять по проводам и не может узнать третья сторона. Хотите шифрование? Там ключ, все готово к работе. Именно так определен защищенный SRP SSL в RFC 5054.

1 голос
/ 04 августа 2009

Подключение сервера к базе данных

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

Подключение пользователя к серверу

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

Нет, правда. Используйте чужую систему паролей. Не создавай свой собственный.

Хорошим решением может быть использование Secure Remote Password Protocol .

1 голос
/ 04 августа 2009

Вы правы, если вы не используете SSL, то пароли могут быть перехвачены.

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

Вы действительно должны обратить внимание на безопасность соединения, чтобы пароль был безопасным при вводе пользователем.

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

0 голосов
/ 04 августа 2009

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

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

Я написал подобное приложение более 15 лет назад. Тогда PGP был моим выбором. Я даже не уверен, что это все еще вокруг.

0 голосов
/ 04 августа 2009

Не уверен, что это то, что вы просите. Но простой пример PHP с использованием встроенной функции sha1:

// Check the hashed password from the database
if (sha1($salt.$password) == $providedPassword)
{
    // User is authenticated
    return TRUE;
}
else
{
    // User is not authenticated    
    return FALSE;
}

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

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

Главное беспокойство - человек посередине, не понимающий пароль в виде простого текста.

Следует использовать SSL, но описанные выше методы могут быть полезны там, где SSL невозможен.

...