Как правильно передавать идентификатор сессии для бэкэнда?
От: vsb Казахстан  
Дата: 12.10.17 16:20
Оценка:
Фронтэнд на джаваскрипте (или в мобилке, не важно), для него есть 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: Как правильно передавать идентификатор сессии для бэкэнда?
От: Qulac Россия  
Дата: 12.10.17 17:17
Оценка:
Здравствуйте, vsb, Вы писали:

Вообще есть разные способы защитится от этого. Один из вариантов это скрытое поле формы содержащее зашифрованные ключом сервера куки или их хеш. При каждом запросе проверяется соответствие одного другому.
Программа – это мысли спрессованные в код
Re: Как правильно передавать идентификатор сессии для бэкэнда?
От: Stalker. Австралия  
Дата: 13.10.17 00:03
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Но так никто не делает, поэтому вопрос — что я понимаю не так?


это называется CSRF атака. В веб приложениях ASP.NET MVC как указал Qulac это защищается функцией antiforgerytoken(), которая записывает кодовое значение одновременно в куку и в скрытое поле формы, и если они не совпадают — реквест будет отклонен.
Для REST подход очень похожий — в токен в виде одного из клеймов записывается кодовое значение, и дополнительно создается отдельный хэдер который содержит то-же самое значение, но не является кукой и может быть прочитан java script'ом. При отправке ответа java script, прочитав его из изначального хэдера, создает ответный хэдер с этим-же значением, и сервер просто проверит что-бы значение в токене и ответном хэдере совпали. Т.к. тот хэдер не являлся кукой, то браузер не отправит его автоматически, и CSRF атака не сработает. В Angular это вообще автоматизированно, и достаточно создать куку XSRF-TOKEN, и ангуляр сам сгенерирует нужный ответный хэдер.
Однако очевидно, что защитившись от CSRF, мы теперь открыты к XSS атакам, т.к. полагаемся на java script клиента. Но с XSS справится уже легче используя рекомендуемые подходы
Re: Как правильно передавать идентификатор сессии для бэкэнда?
От: mogadanez Чехия  
Дата: 18.11.17 10:28
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Смысла в серверных сессиях я не вижу, поэтому пока использую простой вариант — в токене кодирую user id, ip address, issue time. Всё это дело защищаю HMac-ом.


все написано до нас уже JWT token

можно в куках не хранить => ajax+header
Re: Как правильно передавать идентификатор сессии для бэкэнд
От: bnk СССР http://unmanagedvisio.com/
Дата: 18.11.17 11:06
Оценка:
Здравствуйте, 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).
Отредактировано 18.11.2017 11:17 bnk . Предыдущая версия .
Re[2]: Как правильно передавать идентификатор сессии для бэкэнд
От: vsb Казахстан  
Дата: 19.11.17 12:34
Оценка:
Здравствуйте, 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).


Я знаю, но не понимаю, зачем он мне нужен, можно и руками это сделать за полчаса.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.