Создание токенов CSRF для нескольких форм на одной странице

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

<form method="post" action="action.php">
   <input type="hidden" id="security_token" name="security_token" value="gTt96phAcretR99rafEjepHebrEZadEdezadagaZ3gAS5es33WReJeZaMADU2AWr" />
   ...
</form>

Проблема в том, что у меня есть несколько форм на одной странице. Должен ли я создать токен безопасности для каждой формы, поэтому security_token_1, security_token_2, или просто я могу вместо того, чтобы генерировать токен безопасности внутри форм, добавьте его в свойство ко всему тегу body, например:

<body data-csrf-token="gTt96phAcretR99rafEjepHebrEZadEdezadagaZ3gAS5es33WReJeZaMADU2AWr">
...
</body>

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

Спасибо за понимание и комментарии.

Ответ 1

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

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

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

Ответ 2

До тех пор, пока вы убедитесь, что злоумышленники не могут получить токен CSRF (например, не включать его в формы, которые относятся к третьим лицам), использование одного токена CSRF должно быть в порядке. Обратите внимание, что с помощью метода "поместить его в тело" вам понадобится JavaScript для отправки форм, поэтому вы все равно можете вставить его в каждую форму, даже если вы используете только один центральный токен.

Руководство OWASP говорит:

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

то есть. нет необходимости использовать больше одного токена.

Использование отдельных токенов просто имеет то преимущество, что если вам каким-то образом удалось скомпрометировать некоторые, но не все из них (довольно маловероятно, потому что, например, XSS будет компрометировать их все), параметры злоумышленника будут ограничены.