Страшно «держать меня в системе» и проверка сеанса - PullRequest
36 голосов
/ 03 августа 2011

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

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

Проверка сеанса

Итак, прежде всего, вот схема (насколько я понимаю), как проверить, что пользователь может получить доступ только к контенту «только для членов». (этот код идет вверху страницы для проверки и установки таких переменных, как $loggedin = true;)

Session Checking Diagram

В моем нынешнем виде $_SESSION['loggedin'] - это просто имя пользователя. Насколько я понимаю, сеансы могут быть сфальсифицированы или захвачены из одного домена, и поэтому я знаю, что это очень небезопасно (например, злоумышленник может каким-то образом создать сеанс, содержащий другое имя пользователя и вуаля - мгновенный доступ к этому материалу пользователя) Но я не знаю, как я должен проверять сессию. Единственный способ представить это - подключаться к базе данных каждый раз, когда страница загружается, и проверять хеш MD5 или что-то еще из базы данных (и обновлять его), но я думаю, что это создаст много ненужного серверного трафика, и я Я почти уверен, что есть лучший способ сделать это.

Вход в систему

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

Logging In Diagram

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

Итак, мои вопросы:

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

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

Ответы [ 3 ]

8 голосов
/ 03 августа 2011

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

Если вы хотите предотвратить нападение посредника, вам следует использовать HTTPS.

Использование HTTPS гарантирует, что:

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

Основными недостатками HTTPS являются:

  • вам нужно будет приобрести сертификат
  • шифрование увеличит накладные расходы, как в сетевом трафике, так и в использовании ресурсов.
  • данные, отправленные по HTTPS, не будут кэшироваться
4 голосов
/ 03 августа 2011

Очень красиво иллюстрированный вопрос!

Следует отметить, что поддержка PHP-сессий заключается в том, что она тоже использует куки. PHP автоматически устанавливает cookie с идентификатором сессии, который назначает PHP. Затем он автоматически читает этот файл cookie и загружает сеанс.

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

Единственная реальная защита от таких угонов - иметь зашифрованное соединение, то есть соединение "https". Затем данные cookie, отправляемые взад и вперед, будут шифроваться для каждого запроса, поэтому кто-то другой не сможет скопировать его фактическое содержимое.

В противном случае у вас есть правильное представление о том, как сопоставить cookie-файл с постоянным входом в систему для пользователя (т. Е. Хэш в cookie-файле должен совпадать с таким же в базе данных). Для проверки сеанса вам не нужно никакого хэширования, поскольку сами данные сеанса никогда не покидают сервер. Таким образом, вы можете просто установить $_SESSION['logged_in_user_id'] в UID - или в false / null, если они не вошли в систему. То есть, если cookie проверяется или имя пользователя / пароль проверяются, затем установите идентификатор пользователя в сессия как простой int.

Что касается «ручного» входа в систему, когда пользователь отправляет свое имя пользователя и пароль, вы снова подвергаетесь воздействию человека в середине атаки. Как и раньше, это просто вопрос перехвата данных, отправляемых на сервер. Если вы не используете зашифрованное соединение, файлы cookie и имя пользователя / пароль (и все остальное) будут в открытом тексте и легко читаемыми для злоумышленника.

Незначительные баллы:
Для алгоритма хеширования я бы выбрал sha1, а не более старый md5. И для имени пользователя / пароля в базе данных, никогда не стоит хранить пароль как открытый текст в базе данных. Если ваша база данных будет взломана, злоумышленники могут просто прочитать там все, независимо от того, насколько безопасно ваш сервер взаимодействует с вашими пользователями.

Вы, наверное, уже знаете все это, но на всякий случай: для таблицы пользователей сохраните имя пользователя в виде открытого текста, но также сгенерируйте соль (скажем, хешируйте текущее время плюс произвольную - но постоянную! - определяемую вами строку, и хэш это несколько раз несколько раз). Сохраните соль в базе данных и используйте ее при хешировании пароля. И снова, хэшируйте это многократно много раз. Наконец, сохраните хешированный пароль в БД. Вы не сможете отправлять людям их пароли, потому что вы тоже не знаете (вы просто знаете хеш), но вы можете реализовать опцию «сбросить пароль», которая генерирует новую соль и случайную строку, которая Вы тогда хешируете как любой другой пароль. Просто не забудьте хранить новый пароль без хеширования достаточно долго, чтобы отправить его пользователю. Причина, по которой вы хотите хэшировать его несколько раз, заключается в том, что он делает невозможным использование радужного стола для «реверсирования» хеширования, даже если вы знаете соль (и). Если вы только что хешировали пароль один раз, с md5 и без соли, было бы тривиально посмотреть хеш и посмотреть, что такое нехэшированный пароль (если только ваши пользователи не достаточно умны, чтобы использовать действительно длинные случайные пароли, которые не встречается в любых радужных таблицах).

Короче говоря: сеанс, файлы cookie и имя пользователя / пароль уязвимы для одного и того же вида атаки. Наиболее практичной защитой от этого является использование SSL (поскольку, как вы заметили, IP-адреса меняются).

Также смотрите другие ответы. Чем больше информации, тем лучше :) 1027 *

3 голосов
/ 03 августа 2011

как мне проверить, что мои сеансы не являются поддельными?

Установив переменную при создании.

session_start();
if(empty($_SESSION) || !isset($_SESSION['notfake']){
   $_SESSION = array();
   session_regenerate_id();
   $_SESSION['notfake']=1;
}

как мне проверить мои кукине подделка?

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

Будет ли мой метод входа в систему достаточно безопасным после проверки?

Зависит, вы используете HTTPS для всего?Кроме того, установите cookie-файл сеанса только для https.

Есть ли что-то важное, что я пропустил?

Для важных действий (изменение пароля / электронной почты / и т. Д.), потребуйте от пользователя пополнить свой пароль.Кроме того, не используйте plain hash, добавьте некоторую фиксированную строку (= salt) к значениям до хэширования, чтобы избежать прямого использования радужных таблиц.

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