Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.Net MVC CSRF Prevention for JSON POST

I'd like to close the CSRF vulnerability for posting raw JSON via AJAX.

I'm familiar with MVC's mechanism for automating CSRF prevention using the ValidateAntiForgeryTokenAttribute and @Html.AntiForgeryToken(); however, if I understand correctly, this mechanism requires that the POST be done with a Content-Type of application/x-www-form-urlencoded (or similar). Is there a built-in mechanism in ASP.Net MVC that will reject CSRFs for POST requests with Content-Type of application/json? If not, am I stuck with putting the anti-forgery into the JSON object itself? Can you recommend a technique for protecting JSON POST requests from CSRF vulnerability with the same level of security as the form-based approach built into ASP.Net MVC?

like image 684
FMM Avatar asked Sep 01 '11 15:09

FMM


People also ask

Is CSRF possible on post request?

Applications can be developed to only accept POST requests for the execution of business logic. The misconception is that since the attacker cannot construct a malicious link, a CSRF attack cannot be executed.

Is JSON vulnerable to CSRF?

Introduction — CSRF: In this write up I will explain how to identify the JSON CSRF vulnerability and the challenge I face to escalate this bug in a recent project. Generally, the JSON CSRF is not always possible in every web application that uses the JSON body. Mainly it depends on the authentication mechanism.


1 Answers

This question brings up an interesting discussion.

Provided that the request Content-Type is application/json, then CSRF is not a concern. This is because application/json requests must be submitted via XmlHttpRequest, and the cookie which is a necessary part of the verification of your AntiForgeryToken cannot be passed cross-site, but must adhere to the Same Origin Policy.

However, it is possible for a malicious user to submit a request via application/x-www-form-urlencoded which contains the information which will appear to be a valid JSON request, and which will pass any authorization cookies back to your application. There is a more detailed discussion of this at http://forums.asp.net/t/1624454.aspx/1?MVC3+JSON+Model+binding+not+working+with+AntiForgery and at http://aspnet.codeplex.com/workitem/7472, where I post a proof-of-concept.

While it is possible to include the __RequestVerificationToken in a JSON request, a better line of defense is to create an Attribute to verify that a request is of type application/json, since any other request being submitted to your action which expects JSON is in fact invalid, and should not be handled.

I expect that this security issue will be addressed in MVC 4.

UPDATE:

Here is a simple AuthorizeAttribute class you can use to decorate any actions which expect to receive 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;
         }
    }
}
like image 171
counsellorben Avatar answered Sep 28 '22 06:09

counsellorben