Чтобы защитить от CSRF, вы должны поместить nonce в скрытое поле в форме, а также в cookie или в переменной сеанса. Но что, если пользователь открывает несколько страниц на разных вкладках? В этом случае каждая вкладка будет иметь форму с уникальным номером nonce, но в переменной сеанса или cookie будет только одно значение nonce. Или если вы попытаетесь сохранить все nonces в переменной cookie/session, как бы вы определили, какой из них принадлежит к какой форме?
Защита CSRF путем сохранения nonce в переменной Session и форме
Ответ 1
Вы можете сохранить тот же самый номер в каждой из форм. Самый простой способ сделать это - связать nonce с идентификатором сеанса, чтобы эти формы работали только в этом сеансе.
Вам захочется сделать так, чтобы злоумышленникам удалось получить идентификаторы сеансов snarf и создать их собственные nonces. Таким образом, один из способов сделать это - использовать HMAC-SHA256 (или тому подобное) для хеширования идентификатора сеанса, используя ключ, который вы не публикуете публике.
(Очевидно, что если злоумышленник может получить сам идентификатор сеанса, он уже может совершать захват сеанса. Таким образом, это не то, о чем я говорю, а скорее способность злоумышленника создавать script (который работает на компьютер-жертва), который может каким-то образом захватить идентификатор сеанса и использовать его для динамического создания URL-адреса с незаполненным незанятым.)
ETA: зависит ли вышеприведенный подход от того, как долго вы ожидаете, что ваши типичные сеансы продолжатся. Если пользователи обычно используют длительные сеансы продолжительностью более нескольких часов, вам нужно использовать что-то более сложное.
Один из подходов заключается в создании нового nonce для каждой формы, содержащей временную метку, а также hash(timestamp . sessionid)
(где hash
- это некоторый вариант HMAC, как описано выше, для предотвращения подделки, а .
- строка конкатенация). Затем вы проверяете nonce на:
- проверка метки времени, чтобы гарантировать, что значение nonce достаточно свежее (это зависит от вашей политики, но несколько часов типичны).
- затем, вычисляя хеш на основе метки времени и идентификатора сеанса и сравнивая с nonce, чтобы убедиться, что nonce является аутентичным
Если проверка nonce не удалась, вам нужно будет отобразить новую форму, предварительно заполненную представлением пользователя (чтобы, если они потратили целый день на запись своего сообщения, они не потеряют всю свою тяжелую работу), а также свежие ноты. Затем пользователь может повторно отправить запрос успешно.
Ответ 2
Некоторые люди генерируют токен для каждой формы, и это очень безопасный подход. Тем не менее, это может сломать ваше приложение и разозлить пользователей. Чтобы предотвратить все XSRF против вашего сайта, вам просто нужна уникальная 1 токена-переменная за сеанс, а затем злоумышленник не сможет подделать какой-либо запрос, если он не сможет найти этот 1 токен. Незначительная проблема с этим подходом заключается в том, что злоумышленник может переборщить этот токен, пока жертва посещает веб-сайт, который контролирует злоумышленник. ОДНАКО, если токен довольно большой, как 32 байта или около того, тогда потребуется много лет для перебора, а сеанс http должен истечь задолго до этого.
Ответ 3
То, что вы описываете, больше не является nonce (nonce = number used once), это просто идентификатор сеанса. Весь смысл nonce заключается в том, что он действителен только для подачи одной формы, поэтому обеспечивает большую безопасность от угона, чем просто идентификатор сеанса, но за счет того, что не может иметь несколько вкладок, работающих параллельно на сайте.
Nonces являются излишними для многих целей. Если вы их используете, вы должны устанавливать и требовать их только на формах, которые вносят критические изменения в систему, и обучать пользователей тем, что они не могут ожидать использования более одной такой формы параллельно. Страницы, которые не устанавливают nonce, должны позаботиться о том, чтобы не очистить ранее сохраненное nonce от сеанса, так что пользователи могут по-прежнему использовать несвязанные страницы параллельно с не связанной формой.
Ответ 4
Долгое время назад этот пост был написан. Я реализовал блокиратор csrf, который почти наверняка хорошо защищает. Он работает с несколькими открытыми окнами, но я по-прежнему оцениваю, какую защиту он предлагает. Он использует подход БД, т.е. хранение вместо сеанса в таблице. ПРИМЕЧАНИЕ. Я использую MD5 в этом случае как простой механизм анти-sqli
Псевдокод:
FORM:
token = randomstring #to be used in form hidden input
db->insert into csrf (token, user_id) values (md5(token),md5(cookie(user_id))
- токен затем сохраняется в db до тех пор, пока он не получит доступ к действию script, ниже:
ACTION SCRIPT:
if md5(post(token)) belongs to md5(cookie(user_id))
#discard the token
db -> delete from csrf where token=md5(post(token)) and user_id=md5(cookie(user_id))
do the rest of the stuff