Фронтэнд на джаваскрипте (или в мобилке, не важно), для него есть REST-подобное API на бэкэнде, всякие GET /products/123. Имеются юзеры разных типов с разными правами. Для юзера сайт должен выглядеть обычным образом (логин/логаут). Соответственно с каждым запросом должен передаваться какой-то токен, из которого бэкэнд вытащит информацию о юзере и использует её для авторизации запроса.
Смысла в серверных сессиях я не вижу, поэтому пока использую простой вариант — в токене кодирую user id, ip address, issue time. Всё это дело защищаю HMac-ом.
Основной вопрос в том — как правильно передавать этот токен на бэкэнд, чтобы максимально защититься от всяких атак.
Пока у меня такие рассуждения:
Первая атака это подстановка img src="//bank.com/transfer?from=1&to=2&amount=3" на левом сайте. Соответственно браузер выдаст GET-запрос на bank.com/transfer с правильными куками. Соответственно все запросы, которые что-то могут менять, должны быть не на GET. Такую атаку провернуть крайне легко, я даже на RSDN могу любую картинку в пост вставить. Ну это в принципе просто здравый смысл. Хотя мне и идея того, что GET-запросы кто-то может слать от юзера без его ведома не нравится, но я не представляю, как от этого можно защититься. Проверять Referer на бэкэнде?
Вторая атака это форма form method=post action="//bank.com/transfer..." на левом сайте. Насколько я понимаю, по такой форме можно жамкнуть жаваскриптом, так что пользователь опять же сделает POST-запрос с правильными куками. Вот как от этого защититься — я совсем не понял. Ну опять же Referer проверять, но это как-то не совсем надёжно кажется.
Третья атака это если на моём сайте будет уязвимость и злоумышленник сможет выполнить у клиента произвольный жаваскрипт, пока он находится на сайте. Понятно, что он сможет вызывать любые методы API от его имени. Но ещё он может стащить его токен (сессию) и продолжать их вызывать. Защищаться тут можно двумя способами: во-первых на очень важные вещи просить ввод SMS-кода, во-вторых сделать токен недоступным для жаваскрипта, например HTTP-only кука.
Собственно всё это приводит к какой-то путанице, из которой я сделал один вывод — чтобы максимально защититься от всего, надо всё API полностью спрятать за каким-нибудь PUT-методом и передавать сессию по HTTP-only куке. PUT-запросы с третьего сайта сделать никак не получится, куку жаваскриптом вытащить тоже никак не получится.
Но так никто не делает, поэтому вопрос — что я понимаю не так?
CSRF городить не хочу, какой-то костыль с нетривиальной реализацией.
Re: Как правильно передавать идентификатор сессии для бэкэнда?
Вообще есть разные способы защитится от этого. Один из вариантов это скрытое поле формы содержащее зашифрованные ключом сервера куки или их хеш. При каждом запросе проверяется соответствие одного другому.
Программа – это мысли спрессованные в код
Re: Как правильно передавать идентификатор сессии для бэкэнда?
Здравствуйте, vsb, Вы писали:
vsb>Но так никто не делает, поэтому вопрос — что я понимаю не так?
это называется CSRF атака. В веб приложениях ASP.NET MVC как указал Qulac это защищается функцией antiforgerytoken(), которая записывает кодовое значение одновременно в куку и в скрытое поле формы, и если они не совпадают — реквест будет отклонен.
Для REST подход очень похожий — в токен в виде одного из клеймов записывается кодовое значение, и дополнительно создается отдельный хэдер который содержит то-же самое значение, но не является кукой и может быть прочитан java script'ом. При отправке ответа java script, прочитав его из изначального хэдера, создает ответный хэдер с этим-же значением, и сервер просто проверит что-бы значение в токене и ответном хэдере совпали. Т.к. тот хэдер не являлся кукой, то браузер не отправит его автоматически, и CSRF атака не сработает. В Angular это вообще автоматизированно, и достаточно создать куку XSRF-TOKEN, и ангуляр сам сгенерирует нужный ответный хэдер.
Однако очевидно, что защитившись от CSRF, мы теперь открыты к XSS атакам, т.к. полагаемся на java script клиента. Но с XSS справится уже легче используя рекомендуемые подходы
Re: Как правильно передавать идентификатор сессии для бэкэнда?
Здравствуйте, vsb, Вы писали:
vsb>Смысла в серверных сессиях я не вижу, поэтому пока использую простой вариант — в токене кодирую user id, ip address, issue time. Всё это дело защищаю HMac-ом.
Здравствуйте, vsb, Вы писали:
vsb>CSRF городить не хочу, какой-то костыль с нетривиальной реализацией.
А простейший вариант — не сабмитить все формы браузером (не использовать <form method="post">),
а сабмитить только жаваскриптом, а на сервере проверять что сасабмичено именно жаваскриптом (типа X-Requested-With XmlHttpRequest)?
Или (лучше), пусть скрипт добавляет стандартный хидер, Authorization: Bearer <....>
1. <img src="//bank.com/transfer?from=1&to=2&amount=3" — отпадает, не будет хидера
2. <form method=post action="//bank.com/transfer..." — отпадает из-за CORS, скрипт может делать запросы только на свой сайт
3. Если злоумышленник хозяйничает у тебя на сервере, то IMHO, тебя ничего не спасет.
Для защиты от кражи токенов, следует делать их устаревающими..
Вообще, для формата токенов сейчас есть стандарт (JWT).
Здравствуйте, bnk, Вы писали:
vsb>>CSRF городить не хочу, какой-то костыль с нетривиальной реализацией.
bnk>А простейший вариант — не сабмитить все формы браузером (не использовать <form method="post">), bnk>а сабмитить только жаваскриптом, а на сервере проверять что сасабмичено именно жаваскриптом (типа X-Requested-With XmlHttpRequest)? bnk>Или (лучше), пусть скрипт добавляет стандартный хидер, Authorization: Bearer <....>
Тоже хороший вариант, по сути то же самое, что и использовать нестандартный для браузера HTTP метод.
bnk>2. <form method=post action="//bank.com/transfer..." — отпадает из-за CORS, скрипт может делать запросы только на свой сайт
Вот тут я не совсем понял как оно работает. Вроде бы я могу на одном сайте сделать форму для другого сайта и оно будет работать, если пользователь нажмёт на кнопку. Что мешает жаваскрипту нажать на эту же кнопку? Но заголовки оно в любом случае не отошлёт.
bnk>Для защиты от кражи токенов, следует делать их устаревающими..
А смысл, если пользователь должен оставаться залогиненным. Значит будет какой-то мастер-токен для обновления токенов. Значит его и украдут.
bnk>Вообще, для формата токенов сейчас есть стандарт (JWT).
Я знаю, но не понимаю, зачем он мне нужен, можно и руками это сделать за полчаса.