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

Новый токен CSRF за запрос или NOT?

Итак, я читаю и очень смущен тем, что у меня есть токен CSRF, и я должен генерировать новый токен за каждый запрос или только час или что-то еще?

$data['token'] = md5(uniqid(rand(), true));
$_SESSION['token'] = $data['token'];

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

И как я могу перейти к форме? Просто поместите echo $_SESSION ['токен'] в форму скрытого значения, а затем сравните по submit?

4b9b3361

Ответ 1

Если вы делаете это в запросе формы, тогда вы в основном удаляете возможность для атак CSRF, и вы можете решить еще одну общую проблему: множественное представление формы

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

Обычный сценарий: Пользователь A отправляется на ваш сайт и запрашивает форму A, получает форму A плюс уникальный код для формы A. Когда пользователь отправляет форму A, он должен включать уникальный код, который был только для формы A.

Сценарий атаки CSRF: Пользователь A отправляется на ваш сайт и запрашивает форму A. Между тем они посещают другой "плохой" сайт, который пытается атаковать CSRF на них, заставляя их подчиняться поддельная форма B.

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

Но если вы сделаете это как общий токен, продержавшись в течение часа (например, вы разместили выше), то атака выше может работать, и в этом случае вы не достигли значительных успехов в своей защите CSRF. Это связано с тем, что приложение не знает, что форма B никогда не запрашивалась в первую очередь. Это общий токен. ВЕСЬ ТОЧКА CSRF-предотвращения состоит в том, чтобы сделать каждый маркер формы уникальным для этой формы

Изменить: потому что вы запросили дополнительную информацию: 1 - вам не нужно делать это на запрос формы, вы можете делать это в час/сеанс и т.д. Точка - это секретное значение, которое предоставляется пользователю, и повторно отправляется по возврату. Это значение не известно на другом веб-сайте и, следовательно, не может представить ложную форму.

Таким образом, вы либо генерируете токен для каждого запроса, либо за сеанс:

// Before rendering the page:
$data['my_token'] = md5(uniqid(rand(), true));
$_SESSION['my_token'] = $data['my_token'];

// During page rendering:
<input type="hidden" name="my_token" id="my_token" value="<? php echo $_SESSION['my_token']?>" />

// After they click submit, when checking form:
if ($_POST['my_token'] === $_SESSION['my_token'])
{
        // was ok
}
else
{
          // was bad!!!
}

и потому, что это "за форму" - вы не получите двойные формы - потому что вы можете стереть токен после подачи первой формы!

Ответ 2

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

Если вы боитесь, что токен может просочиться или получить полученный атакующий сайт (например, XSS), вы можете ограничить срок действия токенов до определенного таймфрейма, определенной формы/URL-адреса или определенного количество использований.

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

Поэтому моя рекомендация - просто использовать один токен на пользователя/сеанс. И если вам нужна дополнительная безопасность, используйте один токен для каждой формы/URL-адреса для каждого пользователя/сеанса, так что если токен для одной формы/URL-адреса просочится, остальные все еще безопасны.

Ответ 3

Ответ на ваш вопрос: это зависит.

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

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

Нет, вам нужна процедура, которая может генерировать токен для временного кадра. Скажем, вы делите время на 30 минут. Вы создаете один токен за текущие 30 минут в форме.

Когда будет отправлена ​​форма, и вы проверите токен против сейчас и против предыдущего 30-минутного периода. Поэтому токен действителен в течение 30 минут до одного часа.

$token = function($tick = 0) use($secret, $hash) {
    $segment = ((int) ($_SERVER['REQUEST_TIME'] / 1800)) + $tick;
    return $hash($secret . $segment);
};

Ответ 4

Вы можете использовать оба метода.

1) Случайный токен для каждого запроса. Чтобы решить проблему несинхронизированных токенов, вы можете использовать события, отправленные сервером http://www.w3.org/TR/eventsource/ или websockets http://www.w3.org/TR/websockets/ технология связи для обновления токенов в режиме реального времени для каждой страницы.

2) Вы можете использовать токен на сеанс пользователя (не нужно делать это в час), который проще реализовать. У вас не будет проблем с синхронизацией, но если токен не слишком силен, его можно догадаться. Ofcorse, если токен очень случайный, для ненаправленного человека будет очень сложно фактически выполнить подделку запроса.

P.S. первый метод является самым безопасным, но его сложнее реализовать и использовать больше ресурсов.