Подтвердить что ты не робот

Использование MVC3 AntiForgeryToken в HTTP GET, чтобы избежать уязвимости Javascript CSRF

Что касается этого блога Haacked, я не решаюсь реализовывать предлагаемые анти-JSON GET угон-решения, поскольку

  • Рекомендуемые решения по предотвращению угона JSON включают в себя не-REST-полные JSON POST для получения данных

  • Альтернативное решение (обертка объекта) вызывает проблемы с сторонними элементами управления. У меня нет доступа к исходному коду.

  • Я не могу найти реализацию, протестированную сообществом, которая реализует альтернативное решение (см. ниже) о том, как составить токен безопасности или безопасно доставить его на веб-странице. Я также не буду утверждать, что достаточно эксперта, чтобы катить мою собственную реализацию.

  • На заголовки рефереров нельзя полагаться

Фон

Этот блог описывает проблему CSRF, касающуюся JSON Hijacking, и рекомендует использовать JSON POST для получения данных. Поскольку использование HTTP POST для GET данных не очень REST-полно, я бы поискал более RESTfull решение, которое позволяет REST-действия за сеанс или на страницу.

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

Альтернативная реализация

Мне кажется естественным расширить использование ASP.NET MVC AntiForgeryToken с помощью jQuery HTTP GET для моего JSON.

Например, если я получаю некоторые конфиденциальные данные, в соответствии с приведенной выше ссылкой Haacked, следующий код уязвим:

$.getJSON('[url]', { [parameters] }, function(json) {
    // callback function code
});

Я согласен с тем, что RESTfull не дает данных GET с использованием рекомендуемого метода обхода POST. Моя мысль - отправить токен проверки в URL. Таким образом, злоумышленник в стиле CSRF не будет знать полный URL. Кэшированные или не кэшированные, они не смогут получить данные.

Ниже приведены два примера того, как можно выполнить запрос JSON GET. Я не уверен, какая реализация наиболее эффективна, но может догадаться, что первый из них более безопасен из ошибочных прокси-серверов, кэширующих эти данные, что делает его уязвимым для злоумышленника.

http://localhost:54607/Home/AdminBalances/ENCODEDTOKEN-TOKEN-HERE

или

http://localhost:54607/Home/AdminBalances?ENCODEDTOKEN-TOKEN-HERE

... который также может быть MVC3 AntiForgeryToken, или вариант (см. swt). Этот токен будет установлен как встроенное значение для любого формата URL, выбранного выше.

Примеры вопросов, которые мешают мне выполнить собственное решение

  • Какой формат URL (выше) вы использовали бы для проверки JSON GET (слэш, вопросительный знак и т.д.) Будет ли прокси отвечать на http://localhost:54607/Home/AdminBalances с помощью http://localhost:54607/Home/AdminBalances?ENCODEDTOKEN-TOKEN-HERE данные

  • Как бы вы доставляли этот кодированный токен на веб-страницу? Inline или как переменная страницы?

  • Как бы вы создали токен? Построено в AntiforgeryToken или другими способами?

  • В AntiForgeryToken используется файл cookie. Будет ли в этом случае использоваться/необходим резервный файл cookie? Только HTTP? Как насчет SSL в сочетании с HTTP Only?

  • Как бы вы установили заголовки кеша? Что-нибудь особенное для Google Web Accelerator (например)

  • Каковы последствия только того, чтобы запрос JSON запрашивал SSL?

  • Должен ли возвращенный массив JSON по-прежнему быть обернут в объект только ради безопасности?

  • Как это решение будет взаимодействовать с Microsoft, предлагаемым шаблонами и привязкой к файлам функции

Вопросы, приведенные выше, являются причинами, по которым я не продвигаюсь вперед и не делаю этого сам. Не говоря уже о том, что, вероятно, больше вопросов, о которых я не думал, и все же это риск.

4b9b3361

Ответ 1

Asp.net MVC AntiForgeryToken не будет работать через HTTP GET, потому что он полагается на файлы cookie, которые полагаются на HTTP POST (он использует Double Submit Cookies ", описанной в OWASP XSRF Предупреждение об обертке). Вы также можете защитить файлы cookie, отправленные клиенту, указав httponly, чтобы их нельзя было подделать с помощью script.

В этот документ вы можете найти различные методы, которые можно использовать для предотвращения XSRF. Кажется, что вы описали бы вступление в подход 1. Но у нас есть проблема с тем, как получить сеанс на сервере при использовании Ajax HTTP GET-запроса, поскольку файлы cookie не отправляются с запросом. Таким образом, вам также нужно будет добавить идентификатор сеанса к URL-адресу действия (aka. Cookieless session, которые легче захватить). Поэтому, чтобы выполнить атаку, злоумышленник должен был знать только правильный URL-адрес для выполнения запроса GET.

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

В любом случае вам нужно будет развернуть свою собственную защиту XSRF, если вы не хотите использовать HTTP POST в Asp.net MVC.

Ответ 2

Я пришел к этой проблеме, и решение не было таким тривиальным, но есть фантастический блог, чтобы вы начали, это можно использовать с get и post ajax.

http://johan.driessen.se/posts/Updated-Anti-XSRF-Validation-for-ASP.NET-MVC-4-RC

Если вы поместите следующее в глобальное пространство имен, все ваши сообщения/получатели могут воспользоваться наличием токена анти-подделки, и вам не нужно изменять ваши вызовы ajax. Создайте элемент ввода на общей странице.

<form id="__AjaxAntiForgeryForm" action="#" method="post">@Html.AntiForgeryToken()</form>

Следующий javascript будет читать анти-подделку tokken и добавить ее в заголовок запроса.

// Wire up the global jQuery ajaxSend event handler.
$(document).ajaxSend(namespace.ajax.globalSendHandler);

// <summary>
// Global handler for all ajax send events.
// </summary>
namespace.ajax.globalSendHandler = function (event, xhr, ajaxOptions) {
    // Add the anti forgery token
    xhr.setRequestHeader('__RequestVerificationToken', $("#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]").val());
};