Этот вопрос вызывает интересную дискуссию.
При условии, что запрос Content-Type равен application/json
, тогда CSRF не имеет значения. Это связано с тем, что запросы application / 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;
}
}
}