Аутентифицировать систему без сеансов - Только куки - Это достаточно безопасно? - PullRequest
6 голосов
/ 09 июля 2011

Мне интересны ваши советы / мнения по поводу этой проблемы безопасности.

Я думал о том, чтобы сделать что-то вроде этого:

  1. Получить хэш MAC (sha256) из встроенной строкииз userId + expirationTime и в виде строки секретного ключа, созданной из некоторой секретной строки и $ _SERVER ['HTTP_USER_AGENT'].
  2. Получите MAC-хэш (sha256) из userId + expirationTime и в качестве ранее созданного хэша секретного ключа (из шага 1)).
  3. Строка сборки из userId | expiration |и ранее сделанный хэш (из шага 2).
  4. Шифрование данной строки (из шага 3) с помощью алгоритма 'rijndael-256'.(семейство функций mcrypt).
  5. Кодирование в base64.
  6. Установить cookie с заданным значением.

Что вы думаете.Это нормально?Что еще я мог бы реализовать с проверкой $ _SERVER ['HTTP_USER_AGENT'], чтобы убедиться, что куки не украдены (кроме IP-адреса)?

PS Из конфиденциальных данных куки будут содержать только userId.

РЕДАКТИРОВАТЬ: Хорошо, чтобы очистить некоторые вещи.Я пытаюсь сделать "безопасную" систему аутентификации, которая не зависит от сеансов.Рассматриваемое приложение построено более или менее как чистый успокоительный API.

Шаг 2:

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

Решение: " Наше решение этой проблемы простое и эффективное. Мы предлагаем использовать HMAC (имя пользователя | срок действия, sk) в качестве ключа шифрования. Это решение имеет следующую- снижение трех хороших свойств. Во-первых, ключ шифрования является уникальным для каждого отдельного файла cookie из-за имени пользователя и срока действия. Обратите внимание, что всякий раз, когда создается новый файл cookie, в файл cookie включается новое время истечения. Во-вторых, ключ шифрованияневозможно подделать, потому что ключ сервера хранится в секрете. В-третьих, ключ шифрования каждого файла cookie не требует хранения на стороне сервера илискорее, внутри cookie он динамически вычисляется сервером.«Из статьи« Безопасный протокол Cookie »Алекса X. Liu1, Джейсона М. Ковача

Шаг 4: Шифрует данные (которые будут выглядеть примерно так:'marko@example.com| 34234324234 | 324erfkh42fx34gc4fgcc423g4 '), чтобы даже клиент не мог точно знать, что находится внутри.

Шаг 5: Кодирование Base64 предназначено только для того, чтобы сделать окончательное значение красивым.

Ответы [ 2 ]

10 голосов
/ 09 июля 2011

Я укушу.

Чтобы сохранить любое подобие состояния, вам необходимо идентифицировать пользователя с помощью ключа какого-либо типа. Этот ключ отправляется в браузер в виде файла cookie ИЛИ через параметры строки запроса.

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

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

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

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

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

Теперь, если вы действительно хотите сделать это правильно, вам нужно включить SSL. Иначе ты зря тратишь время. Весь разговор (с экрана входа в систему) должен быть зашифрован. Если это не так, то кто-то может просто прослушать этот файл cookie, немедленно воспроизвести его и перехватить сеанс. Дело в том, что им не нужно знать содержащиеся в них значения, чтобы использовать их. Таким образом, все хеширование и т. Д., Которое у вас есть, - просто пух, который увеличит нагрузку на ваш сервер.

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


Итак, подведем итог: опубликованный вами метод - пустая трата времени.

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

1 голос
/ 10 июля 2011

@ Marko Несколько комментариев о том, насколько безопасен этот вид «сеанса в cookie»:

Прежде всего, как уже говорили и другие, вам необходимо безопасное соединение.Реального способа обойти это требование не существует.Это необходимо.

Кроме этого, существует множество ловушек, связанных с внедрением безопасной системы шифрования / аутентификации.Например, вам нужно сделать проверку MAC «постоянным временем», вам нужно обратить внимание на то, как вы реализуете шифрование / аутентификацию (режим работы, создание IV и т. Д.).И так далее.

Если вы не уверены в таких проблемах, я рекомендую вам взглянуть на TCrypto (который я поддерживаю):

TCrypto

Это небольшая библиотека хранения значений ключей PHP 5.3+ (файлы cookie будут использоваться в качестве внутреннего хранилища по умолчанию).Предназначен именно для (масштабируемого) использования «сеанса в cookie».Не стесняйтесь использовать его :) Кроме того, если вы заинтересованы в низкоуровневой реализации, взгляните на код.Кодовая база не так уж велика, я думаю, она бы неплохо продемонстрировала использование кода, связанного с шифрованием, в приложениях PHP.

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