ASP.Net MVC CSRF для JSON POST

Я хотел бы закрыть уязвимость CSRF для отправки raw JSON через AJAX.

Я знаком с механизмом MVC для автоматизации предотвращения CSRF с использованием ValidateAntiForgeryTokenAttribute и @Html.AntiForgeryToken(); однако, если я правильно понимаю, этот механизм требует, чтобы POST выполнялся с Content-Type of application/x-www-form-urlencoded (или аналогичным). Есть ли встроенный механизм в ASP.Net MVC, который отклонит CSRF для POST запросов с Content-Type от application/json? Если нет, я застрял в том, чтобы положить анти-подделку в объект JSON? Можете ли вы рекомендовать методику защиты запросов JSON POST от уязвимости CSRF с тем же уровнем безопасности, что и основанный на форме подход, встроенный в ASP.Net MVC?

Ответы

Ответ 1

Этот вопрос вызывает интересное обсуждение.

Если запрос Content-Type имеет значение application/json, то CSRF не является проблемой. Это связано с тем, что запросы приложения /json должны быть отправлены через XmlHttpRequest, а файл cookie, который является необходимой частью проверки вашего AntiForgeryToken, не может быть передан через сайт, но должен придерживаться Одинаковая политика происхождения.

Тем не менее, злоумышленник может отправить запрос через application/x-www-form-urlencoded, который содержит информацию, которая будет отображаться как действительный запрос JSON, и которая будет передавать любые файлы cookie авторизации обратно ваше приложение. Более подробно это обсуждается на http://forums.asp.net/t/1624454.aspx/1?MVC3+JSON+Model+binding+not+working+with+AntiForgery и http://aspnet.codeplex.com/workitem/7472, где я публикую доказательство концепции.

В то время как можно включить __RequestVerificationToken в запрос JSON, лучшая линия защиты - создать Атрибут, чтобы проверить, что запрос имеет тип application/json, поскольку любой другой запрос, передаваемый вашему действию, который ожидает JSON на самом деле недействителен и не должен обрабатываться.

Я ожидаю, что эта проблема безопасности будет рассмотрена в MVC 4.

UPDATE:

Вот простой класс AuthorizeAttribute, который вы можете использовать для украшения любых действий, которые ожидают получить JSON:

public class JsonRequestAttribute : AuthorizeAttribute
{

    /*
     * 
     *   CONFIRM that this is REALLY a JSON request.
     *   This will mitigate the risk of a CSRF attack
     *   which masquerades an "application/x-www-form-urlencoded" request
     *   as a JSON request
     * 
     */

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
         if (!filterContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))
         {
             // This request is masquerading as a JSON request, kill it.
             JsonResult unauthorizedResult = new JsonResult();
             unauthorizedResult.Data = "Invalid request";
             unauthorizedResult.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
             filterContext.HttpContext.Response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest;
             filterContext.Result = unauthorizedResult;
         }
    }
}