Кодирование файлов cookie, чтобы их нельзя было подделать или прочитать и т. Д


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

Я хочу закодировать их или запутать, чтобы их нельзя было прочитать или подделать.

Как лучше всего это сделать?

Обновление:

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

Author: ircmaxell, 2011-02-16

5 answers

Краткий ответ

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

Лучший Способ Сделать Это

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

$randomToken = hash('sha256',uniq_id(mt_rand(), true).uniq_id(mt_rand(), true));

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

$randomToken .= ':'.hash_hmac('md5', $randomToken, $serverKey);

Теперь, когда вы проверяете, сначала проверьте, совпадает ли хэш:

list($token, $hmac) = explode(':', $_COOKIE['remember_me'], 2);
if ($hmac != hash_hmac('md5', $token, $serverKey)) {
    die('tampered token!');
}

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

Я бы также предложил менять токен при каждой смене пароля.

Чтобы ответить на ваш прямой вопрос

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

Чтобы закодировать его, я бы использовал mcrypt для шифрования данных в файле cookie. Затем я бы сделал случайную соль и сохранил ее у пользователя строку, а затем подпишите зашифрованные данные с помощью hash_hmac используя эту уникальную соль. Таким образом, если кто-то перехватит файл cookie и вычислит ключ к шифрованию, вы все равно сможете обнаружить недействительный hmac, чтобы найти несанкционированные вмешательства.

function generateCredentialsCookie($user_id, $password) {
    $encrypted = encrypt($user_id.':'.$password, $secretkey);
    $salt = uniq_id(mt_rand(), true);
    $encrypted .= ':'.hash_hmac('sha256', $encrypted, $salt);
    storeSaltForUser($user_id, $salt);
    set_cookie('credentials', $encrypted);
}

function readCredentialsCookie() {
    $parts = explode(':', $_COOKIE['credentials']);
    $salt = array_pop($parts);
    $encrypted = implode(':', $parts); //needed incase mcrypt added `:`
    $raw = decrypt($encrypted, $secretkey);
    list ($user_id, $password) = explode(':', $raw, 2);
    if ($salt == getSaltForUser($user_id)) 
        return array($user_id, $password);
    } else {
        return die('Invalid Cookie Found');
    }
}

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

НЕ Используйте Длительные Сеансы!

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

Что касается того, почему бы не использовать длительный сеанс, вот некоторые минусы:

  • DOS (Отказ В Обслуживании создаются уязвимости

    • Дисковое пространство - Каждый сеанс использует достаточно небольшой объем дискового пространства. Но когда у вас длительный сеанс, каждый новый сеанс только добавляет к предыдущему итогу. Таким образом, при длительных сеансах кому-то просто нужно продолжать посещать ваш сайт снова и снова с новым идентификатором сеанса, и вдруг у вас не хватает места на диске (при условии, что на нормальном диске).

    • Пространство папок - Каждый сеанс занимает один файл в одной папке. Большинство популярных файловых систем будут замедляться при большом количестве файлов в одной папке. Поэтому, если вы поместите 1 миллион файлов сеанса, чтение или запись в файл сеанса будет медленным (очень медленным). И сборка мусора (которая очищает старые файлы) будет ОЧЕНЬ, ОЧЕНЬ, ОЧЕНЬ медленной (если она вообще будет выполняться).

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

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

 52
Author: ircmaxell, 2011-02-15 22:08:24

Хранение пользовательских данных в файле cookie является неправильным способом. Вы должны использовать Сеансы PHP. Единственное, что будет сохранено на клиенте, - это идентификатор сеанса в простом файле cookie (который PHP обработает для вас автоматически). Это уже зашифрованная строка.

PHP будет отслеживать пользовательские данные на стороне сервера.

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

 4
Author: Stephen, 2011-02-15 21:28:30

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

Пара методов:

Если пользователь выберет "запомнить меня", просто установите следующее перед инициализацией сеанса.

session_set_cookie_params(60 * 60 * 24 * 7); //save cookie session for 7 days

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

Я бы однако рекомендую первый вариант.

 2
Author: John Cartwright, 2011-02-15 21:32:13

Соленое печенье перед сохранением. Добавьте агента пользователя, ip, если вы хотите повысить безопасность.

$cookie_to_save = sha1($pwd . $user_agent . $yourSalt);

При автологине

if($cookie_saved == sha1($pwd . $user_agent . $yourSalt) ok...
 0
Author: Teson, 2011-02-15 21:31:31

Проще сгенерировать 16 или более криптографически защищенных случайных чисел и сохранить их в файле cookie. Нет необходимости в шифровании/расшифровке. Используйте его с ограниченным сроком действия, проверенным на стороне сервера (не полагайтесь на максимальный срок или срок действия). Это файл cookie сеанса.

Это очень безопасно, так как никакая важная информация не покидает сервер.

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

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

Недостатком этого метода является то, что если кто-то узнает ключ, он может подделать файлы cookie. Затем он может создавать файлы cookie с разными идентификаторами пользователей и получать доступ к их учетной записи. Поэтому используйте этот метод там, где риск ограничен, а доступ к ключу хорошо контролируется. Решением может быть специальное аппаратное устройство, выполняющее шифрование/расшифровку и скрывающее ключ. Но в настоящее время это необычно и дорого. Это задержка может быть больше, чем просто поиск до случайного идентификатора сеанса в кэше. Чем позже, тем проще и безопаснее решение.

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

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

 0
Author: chmike, 2017-09-24 08:31:20