Разработка безопасного логина PHP и стратегии аутентификации - PullRequest
8 голосов
/ 16 декабря 2009

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

Я планирую хранить следующие данные:

  • В сеансе: идентификатор пользователя, хэшированный + соленый HTTP_USER_AGENT

  • В файле cookie и в базе данных: случайный токен, хешированный + соленый идентификатор

На каждой странице я планирую сделать следующее:

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

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

  3. Если файл cookie недействителен или не существует, попросите пользователя войти в систему.

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

Большое спасибо заранее.

Ответы [ 8 ]

12 голосов
/ 16 декабря 2009

Несколько случайных мыслей:

  1. Что если я украду куки-файл одного из ваших пользователей (используя XSS-атаку, внедрив некоторый код JS на ваш сайт)? Затем я попаду в случай 2. и, таким образом, смогу войти в систему. ИМХО, если вы хотите действительно безопасную аутентификацию, не используйте куки типа «запомнить меня» для хранения учетных данных пользователя.
  2. Если вы сохраняете учетные данные в файле cookie, не храните пароль в открытом виде.
  3. Проверка на HTTP_USER_AGENT является хорошим первым шагом для предотвращения перехвата сеанса, но, возможно, вы могли бы объединить его с IP-адресом? Находиться на том же хосте, что и вы, гораздо сложнее, чем просто использовать один и тот же браузер.

Но в любом случае, спасибо, что нашли время подумать о хорошей схеме аутентификации. Многие разработчики PHP этого не делают.

РЕДАКТИРОВАТЬ: для протокола, позвольте мне уточнить здесь: в этом обсуждении есть два куки. Один из них устанавливается автоматически PHP для распространения идентификатора сеанса (иногда мы видим, что веб-сайты помещают его в URL, например, www.example.com/page.php?sessionId = [...]), а второй создается вами. для того, чтобы сохранить учетные данные пользователя и аутентифицировать его, когда сеанс потерян. Атака XSS применяется к обоим, т. Е. Злоумышленник может либо украсть файл cookie сеанса и захватить сеанс (срок его действия ограничен), либо украсть файл cookie учетных данных и выполнить проверку подлинности позже.

2 голосов
/ 17 декабря 2009

Хранение cookie в базе данных - идея HORRILBE. Это означает, что если у злоумышленника была уязвимость SQL-инъекций, он мог бы сразу получить доступ, не взламывая хешированный пароль.

Говоря о том, что вам нужно использовать sha256 для паролей, если вы используете md5 (), вы технически уязвимы для атаки и вам может быть выдан номер CVE.

НИКОГДА не создавайте свои собственные идентификаторы сеансов, используйте session_start () и суперглобальную переменную $ _SESSION.

Это безопасный способ перенаправления людей. Если вы не умрете после header (), оставшаяся часть php-кода будет STILL EXECUTED, даже если она не отображается обычными браузерами (хакеры все еще видят это:)

header("location: index.php");
die();

Если честно, если безопасность вас смущает, не пишите системы безопасности. Люди написали более 1000 систем входа в систему только для PHP, и большинство из них уязвимы. Этот проект имеет безопасную систему аутентификации: http://code.google.com/p/michael-the-messenger/downloads/list

2 голосов
/ 16 декабря 2009

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

Джо

1 голос
/ 20 января 2010

Большинство сайтов просто используют сессию PHP; данные сеанса ($ _SESSION) находятся в файле на вашем сервере. Все, что отправлено в браузер - это идентификатор сессии. Обязательно повторяйте сеанс каждый запрос ( session_regenerate_id ). Вам не нужно отправлять два куки или что-то еще.

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

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

1 голос
/ 17 декабря 2009

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

  1. Любые данные, отправляемые браузером (например, файлы cookie, User-agent), могут быть поддельными. Проверка User-agent поможет только тогда, когда злоумышленник находится за тем же NAT, что и поддельный пользователь, и злоумышленник использует другой браузер, но не думает сменить User-agent.
  2. Сеансы сохраняют идентификатор сеанса на стороне клиента, используя куки или параметр запроса URL. Если вы хотите продлить срок жизни сеанса, используйте session_set_cookie_params, чтобы сохранить файл cookie сеанса дольше.

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

Атаки, которые cookie-файл сеанса + проверка удаленного IP-адреса не перехватывают:

  1. злоумышленник находится за тем же NAT, что и пользователь
  2. Атака вслепую, когда злоумышленник подделывает IP-адрес пользователя. Несмотря на то, что они предназначены только для записи, они могут нанести некоторый ущерб.
  3. атак с использованием собственного браузера пользователя, например подделка межсайтовых запросов (CSRF).

2) можно было бы предотвратить, если бы вы могли выработать способ отправки запроса в браузер пользователя, на который необходимо ответить перед завершением запроса, но это сложно, когда вы не написали клиент. С AJAX это можно сделать. 3) (как отмечено MindStalker) можно предотвратить, проверив заголовок Referer, который работает, потому что CSRF-атаки не имеют возможности влиять на произвольные заголовки, а XMLHttpRequest не должен позволять устанавливать заголовок Referer (согласно стандарт W3C , хотя реализации могут быть несовместимы). С помощью iframes можно обойти проверку Referer. Кроме того, заголовок Referer может быть заблокирован на стороне клиента.

1 голос
/ 16 декабря 2009

Зависит от того, насколько безопасно вы хотите быть ..

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

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

0 голосов
/ 01 августа 2016

- используйте sha1 с солью - Конечно, вы должны определить, что каждая форма не является безопасной, поэтому для каждой формы используется токен. Чтобы вы создали каждую запись формы и очистили ее, используя preg_match. Процесс называется санитарией.

0 голосов
/ 20 января 2010

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

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