Подтвердить что ты не робот

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

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

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

Каков наилучший способ сделать это?

Update:

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

4b9b3361

Ответ 1

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

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

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

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

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

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

$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 (Denial Of Service)

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

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

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

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

Ответ 2

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

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

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

Ответ 3

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

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

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

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

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

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

Ответ 4

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

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

при автологе

if($cookie_saved == sha1($pwd . $user_agent . $yourSalt) ok...

Ответ 5

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

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

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

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

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

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

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