Меня интересуют ваши советы и мнения по этой проблеме безопасности.
Я думал о том, чтобы сделать что-то вроде этого:
Как вы думаете. Это нормально? Что еще я мог бы реализовать с проверкой $ _SERVER ['HTTP_USER_AGENT'], чтобы убедиться, что cookie не украден (кроме IP-адреса)?
PS Из конфиденциальных данных cookie будет содержать только userId.
EDIT: Хорошо, чтобы очистить некоторые вещи. Я пытаюсь сделать «безопасную» систему auth, которая не полагается на сеансы. Приложение, о котором идет речь, построено более или менее как чистый успокоительный api.
Шаг 2:
Проблема: «Протокол Фу не дает ответа на этот вопрос. В протоколе Фу есть только один ключ, а именно ключ сервера. Одно прямое решение – использовать этот ключ сервера для шифрования поля данных каждого файла cookie , но это решение небезопасно ».
Решение: «Наше решение этой проблемы прост и эффективен. Мы предлагаем использовать HMAC (имя пользователя | время истечения, sk) в качестве ключа шифрования. Это решение имеет следующие три хороших свойства. Во-первых, ключ шифрования уникален Обратите внимание, что всякий раз, когда создается новый файл cookie, в файл cookie входит новое время истечения срока действия. Во-вторых, ключ шифрования является неприменимым, поскольку ключ сервера хранится в секрете. В-третьих, ключ шифрования каждого файла cookie не требует какого-либо хранения на стороне сервера или внутри файла cookie, скорее, он динамически выводится сервером ». Из статьи« Безопасный протокол cookie »от Alex X. Liu1, Jason M Ковач
Шаг 4: Шифрует данные (которые выглядели бы примерно так: «marko@example.com|34234324234|324erfkh42fx34gc4fgcc423g4»), чтобы даже клиент не мог точно знать, что внутри.
Шаг 5: Base64 encode только для того, чтобы сделать окончательное значение симпатичным.
Я буду кусать.
Чтобы поддерживать какое-либо подобие состояния, вам нужно идентифицировать пользователя, используя ключ определенного типа. Этот ключ отправляется в браузер как файл cookie ИЛИ через параметры строки запроса.
Теперь проверка этого ключа может произойти внутри самого веб-сервера (сеанса) или путем проверки другого механизма хранения, как правило, записи базы данных.
Сам ключ должен быть запутан с использованием некоторого механизма. Причиной обфускации является просто усложнение того, какие значения могут иметь другие ключи, если исходный пользователь или кто-то другой решает проверить значение. Например, если ключ является вашим идентификатором пользователя (не рекомендуется), и вы используете инкрементные ints, тривиально угадывать другие пользовательские ключи. Я хочу подчеркнуть, что обфускация (или даже прямое шифрование) ключа обеспечивает абсолютно никакой защиты от захваченного сеанса. Все, что он делает, затрудняет угадывание ключей сеансов других людей .
Тем не менее, я считаю, что ключ не должен иметь ничего общего с вашим идентификатором пользователя и вместо этого быть рядом с случайным значением, например, сгенерированным GUID. Совершенно откровенно, что идентификатор GUID, основанный на базе 64, находится на том же уровне безопасности, что и шифрование идентификатора пользователя + времени. Это просто, что на вашем сервере более интенсивный вычислительный процесс, чем другой.
Конечно, этот ключ может меняться по каждому запросу. Браузер сообщает что-то, вы создаете новый ключ и отправляете его обратно. В случае, если браузер отправляет устаревший ключ, запишите его и отбросьте обратно на экран входа в систему. Это должно помешать повторным атакам .. в какой-то степени. Однако он вводит другие проблемы, такие как использование кнопки «Назад» в разных браузерах. Таким образом, вы можете не захотеть идти по этому пути.
Тем не менее, вы не можете зависеть от IP-адреса клиента, поскольку тот же пользователь может отправлять последующие запросы с использованием другого IP-адреса. Вы не можете зависеть от отпечатка пальца браузера, потому что любой достойный инструмент взлома захватит это и отправит те же значения независимо от того, что они используют.
Теперь, если вы действительно хотите сделать это правильно, вы должны включить SSL. В противном случае вы тратите свое время. Весь разговор (с экрана входа в систему) должен быть зашифрован. Если это не так, тогда кто-то может просто прослушать этот файл cookie, немедленно воспроизвести его и захватить сессию. Дело в том, что им не нужно знать значения, содержащиеся в них, чтобы использовать их. Таким образом, все это хеширование и т. Д. У вас есть просто пух, который увеличит нагрузку на ваш сервер.
Я использовал SSL? 😉 Это зашифрует трафик с начала разговора, и злоумышленник не сможет воспроизвести те же самые пакеты, что и для их собственного рукопожатия с сервером. Это означает, что все, что вам нужно сделать, это убедиться, что любой идентификатор сеанса, который вы используете, недопустим, так что один зарегистрированный пользователь не может перехватить чужую сессию.
Итак, подведем итог: метод, который вы опубликовали, является пустой тратой времени.
Вам намного лучше получить сертификат SSL за 10 долларов и использовать идентификатор GUID, основанный на базе 64, в качестве идентификатора сеанса. Как вы храните информацию о сеансе на своем сервере, это не имеет большого значения … кроме ситуаций с балансировкой нагрузки. В этот момент он должен быть нерабочим и поддерживаться сервером базы данных .. но это другой вопрос.
@Marko Несколько комментариев о том, насколько безопасен такой подход «сеанс в cookie»:
Прежде всего, как говорят другие, вам нужно безопасное соединение. Этого требования не существует. Это необходимо.
Помимо этого, существует множество ошибок, связанных с внедрением системы безопасного шифрования / аутентификации. Например, вам нужно сделать проверку MAC «постоянным временем», вам нужно обратить внимание, как вы реализуете шифрование / аутентификацию (режим работы, создание IV и т. Д.). И так далее.
Если вы не уверены в таких проблемах, я рекомендую вам взглянуть на TCrypto (который я поддерживаю):
TCrypto
Это небольшая библиотека хранения ключей с ключевыми значениями PHP 5.3+ (файлы cookie будут использоваться в качестве хранилища по умолчанию). Предназначен именно для (масштабируемого) использования «сеанса в cookie». Не стесняйтесь использовать его 🙂 Также, если вас интересует реализация на низком уровне, взгляните на код. Кодовая база не такая уж огромная, я думаю, это было бы неплохо, демонстрируя использование кода, связанного с использованием кода, в PHP-приложениях.