Поведение хеш-токена csrf при открытии веб-сайта на нескольких вкладках - PullRequest
2 голосов
/ 02 декабря 2011

Я пытаюсь интегрировать метод для добавления токена в каждую форму в моем приложении. Я хочу достичь целей с помощью этого:

  1. Предотвращение атак CSR
  2. Предотвращение повторной отправки формы, когда пользователь перезагружает страницу после отправки формы

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

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

Пока все хорошо, теперь я действительно застрял в следующем сценарии:

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

Ответы [ 2 ]

2 голосов
/ 02 декабря 2011

Не храните токен как cookie.

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

Сначала мы генерируем токен, где мы можем проверить, что мы выдали его для данного пользователя:

token = hash(session_id + secret)

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

Теперь нам нужно убедиться, что токен можно использовать только один раз.

rnd = rand()
token = rnd + hash(session_id + secret + rnd)

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

Но мы не хотим вечно хранить случайные числа использованных токенов. Поэтому мы ограничиваем время жизни токенов.

rnd = rand()
now = time()
token = rnd + time + hash(session_id + secret + rnd + time)

На POST, когда мы получаем токен, мы теперь проверяем, выпустили ли мы его «недавно». Нам нужно только хранить использованные случайные числа для того же времени. Все старые токены недопустимы по определению.

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

1 голос
/ 04 декабря 2011

Я бы реализовал функции независимо:

Предотвращение CSRF

Использование токена CSRF для предотвращения успешных атак CSRF: Генерация токена random за сеанс или за URL / форму и сохранить его в сеансе.Когда форма первоначально запрашивается, поместите (связанный) токен CSRF и проверьте его позже при обработке отправленных данных формы.

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

Предотвращение многократной отправки формы

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

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

Несколько вкладок или запросов форм не представляют проблемы: токен CSRFдействителен либо в течение всего сеанса, либо для любого представления формы определенного URL / формы.А другой токен действителен только для отправки одной формы.

...