Ответ 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;
}
}
}