Безопасный вход с правильной аутентификацией в PHP - PullRequest
5 голосов
/ 01 сентября 2009

Как мне написать / собрать безопасный вход в PHP? В руководстве разработчика веб-сайта сказано, что я не должен бросать свои собственные, поэтому ссылаться на образцы, доступные через Google, бесполезно.

Как вы, профессионалы, делаете это? Допустим, вы создаете приложение мирового класса в рельсах, будут ли здесь использоваться те же библиотеки / методы?

Спасибо

Ответы [ 6 ]

20 голосов
/ 01 сентября 2009

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

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

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

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

Решение состоит в том, что перед хэшированием пароля его объединяют (обычно сцепляют или xor'd) со значением, называемым солью, которое уникально для каждого пользователя. Это может быть случайно сгенерировано, или это может быть метка времени создания учетной записи или что-то подобное. Тогда злоумышленник не может использовать радужную таблицу, потому что каждый пароль по сути хэшируется немного по-разному; ему придется создать отдельную радужную таблицу для каждой отдельной соли (практически для каждой учетной записи), что будет непомерно дорого в вычислительном отношении.

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

4 голосов
/ 01 сентября 2009

Zend Framework имеет модуль 'Auth' , с которого можно было бы начать. Или, если на вашем сайте будет установлена ​​WordPress или PHPBB, есть способы использовать модули аутентификации этих технологий для входа на другие страницы сайта.

2 голосов
/ 01 сентября 2009

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

Например, на SO я использую свой логин Google, и это работает, поскольку им просто нужно знать, кто я, и они могут верить, что у Google есть идея. Итак, если эта модель будет работать для вас, тогда посмотрите на использование OpenID, поскольку для этого есть различные инструменты.

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

  • Никогда ничего не доверяйте пользователю, если вы не использовали строгую проверку.
  • Используйте https для защиты пароля пользователя, вы им должны.

Я закончу свой ответ здесь, как Том сделал фантастический ответ.

0 голосов
/ 02 сентября 2009

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

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

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

0 голосов
/ 02 сентября 2009

от Soulmerge:

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

  • Используйте https при отправке паролей. Это гарантирует, что никто не сможет поймать их по проводам ( атака "человек посередине" или клиент использует злой прокси)
  • Альтернативой является хеширование пароля с использованием javascript при отправке формы входа. Это гарантирует, что пароль никогда не будет передан в виде открытого текста. Вы должны снова хэшировать хешированное значение с солью на сервере. (md5($_POST['postedPwHash'] . $salt))
0 голосов
/ 01 сентября 2009

Мой ответ "Не делай этого"

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

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

...