Использование MVC3 AntiForgeryToken в HTTP GET, чтобы избежать уязвимости Javascript CSRF - PullRequest
19 голосов
/ 06 февраля 2011

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

  1. Рекомендованные решения для уменьшения использования JSON.задействовать незаполненные REST JSON POST для получения данных

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

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

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

Справочная информация

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

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

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

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

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

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

Я согласен, что НЕ ПОЛУЧИТЬ ПОЛУЧИТЬ данные, используя рекомендованный метод POST.Моя мысль состоит в том, чтобы отправить токен проверки в URL.Таким образом, злоумышленник в стиле CSRF не будет знать полный URL.Кэшированные или не кэшированные, они не смогут получить данные.

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

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

или

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

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

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

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

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

  3. Как бы вы составили токен?Встроенный AntiforgeryToken или каким-либо другим способом?

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

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

  6. Каковы последствия простого создания JSON-запроса SSL?

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

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

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

Ответы [ 2 ]

15 голосов
/ 09 февраля 2011

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

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

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

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

4 голосов
/ 04 сентября 2013

Я пришел к этой проблеме, и решение не было таким тривиальным, однако есть фантастический блог, с которого можно начать, его можно использовать с 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 прочитает токен защиты от подделки и добавит его в заголовок запроса.

// 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());
};
...