Вариант использования:
В ситуации с одним доменом я хочу использовать jsonp для передачи данных, просто потому, что это происходит раньше в запросе, чем любой ajax или iframe транспорт. Кроме того, я хочу, чтобы эти данные кэшировались как обычный файл js.
Я не хочу предоставлять эти данные другим доменам.
Итак, я подумал о следующих приемах, чтобы предотвратить csrf:
- токен csrf, отправленный в качестве параметра GET с запросом.
- Еще один токен csrf, который хранится в переменной до выполнения jsonp. Таким образом, jsonp вызовет функцию, только если найдет, что эта переменная имеет правильное значение.
Это двойное параноидальное решение, потому что я не уверен, является ли какое-либо из этих двух пуленепробиваемым.
Вопросы будут:
- Безопасно ли отправлять токен csrf в параметре GET? Или что я могу сделать, чтобы сделать его безопасным?
- Может ли кто-то из другого домена заглянуть в исходный код js, чтобы обойти трюк с номером (2)?
Чтобы не начинать с нуля, вот документ, который я считаю полезным:
https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet
(но может быть, я что-то там пропустил)
Особенно интересно: «Раскрытие токена в URL», которое, я думаю, я до сих пор не до конца понял во всех его последствиях.
EDIT:
Другие решения, о которых можно подумать:
3. проверка реферера. Не достаточно безопасно, афаик. Особенно, если файл js кэшируется в браузере.
4. Шифрование. Вероятно, не стоит усилий ..
РЕДАКТИРОВАТЬ II:
Для пояснения: «ситуация с одним доменом» означает, что html-страница и jsonp обслуживаются из одного домена. Клиентский компьютер может быть где угодно.
РЕДАКТИРОВАТЬ III:
Я хочу быть таким же безопасным, как если бы я обслуживал обычный json или html / xml (запрашиваемый с помощью ajax или iframe) вместо jsonp. Как вы, вероятно, знаете, json и html / xml защищены политикой того же происхождения, а jsonp - нет.
Я хочу использовать токены csrf для достижения такой же защиты с помощью jsonp. Токены csrf, очевидно, будут обслуживаться со страницей html.
РЕДАКТИРОВАТЬ IV:
Вот как будет выглядеть трюк № 2.
HTML страницы:
<script type="text/javascript">
var token1 = 'upoihjvpaoijpoj';
</script>
<script type="text/javascript" src="xyz/jsonp.js?token2=o8976987698540"></script>
А потом в xyz / json.js? Token2 = ..:
if (token1 == 'upoihjvpaoijpoj') {
json_callback(data);
}
РЕДАКТИРОВАТЬ V:
Это достаточно сложный вопрос, поэтому я должен добавить пример из реальной жизни. Я не помню точный случай использования, когда я отправил этот вопрос, поэтому я просто пишу что-то, что подходит.
Типичным примером может быть раскрывающееся меню, в которое мы хотим загрузить содержимое меню с помощью отдельного запроса, поскольку они одинаковы на каждой странице. Тем не менее, меню может содержать некоторые ссылки, которые должны отображаться только для определенных пользователей, вошедших в систему. Давайте просто предположим, что несанкционированные посетители никогда не увидят эти ссылки. Это дело жизни и смерти.
Первой идеей было бы загрузить меню с запросом XHR. На стороне сервера мы можем проверить cookie / сессию, чтобы проверить, вошел ли пользователь в систему, и предоставить персонализированное меню.
Но XHR может начать загружаться только после того, как остальная часть страницы уже там. Javascript, с другой стороны, может начать загрузку, как только браузер анализирует заголовок HTML. Таким образом, мы могли бы надеяться на выигрыш в производительности, если бы обслуживали данные меню с помощью javascript / jsonp вместо XHR.
Теперь сценарий CSRF:
- Пользователь входит на oursite.com, который создает cookie-файл сеанса.
- Затем тот же пользователь посещает сайт злоумышленника evil.com, на котором есть тег сценария для запроса (персонализированного) oursite.com/menudata.js.
- Из-за политики одного и того же происхождения скрипты на evil.com не могут напрямую проверять содержимое файла menudata.js. Вместо этого он просто запустит menudata.js.
menudata.js может выглядеть так:
spawnMenu({...});
Или spawnMenu может быть динамически выбранной строкой, основанной на параметрах запроса.Если menudata.js выполняется на evil.com, злоумышленники, работающие на этом сайте, могут предоставить функцию с таким именем, а затем «позвонить домой» и украсть данные персонализированного меню.
Теперь идея (пункт 2 изпервоначальный вопрос) было сделать что-то вроде этого в menudata.js:
if (secret_var === 'opijpoijpoizvnpoiq92823pjnfn') {
spawnMenu({...});
}
Сначала это выглядит вполне нормально.evil.com не знает secret_var, поэтому при запуске menudata.js он ничего не сделает.
Но потом я услышал, что есть некоторые неприятные приемы, с помощью которых можно «переписать» довольно базовые части js.Например, заменить обычный способ, которым материал приводится к строке.Может быть, даже заменить операторы сравнения?Таким образом, скрипт на evil.com мог бы обмануть нашу миленькую проверку.