119

I've been getting the same old error every time I test a new URL from my browser's address bar when I'm returning Json (using the built-in MVC JsonResult helper):

This request has been blocked because sensitive information could be disclosed to third party web sites when this is used in a GET request. To allow GET requests, set JsonRequestBehavior to AllowGet.

Rather than grunt in acknowledgement and fire up Fiddler to do a post request, this time, I'm wondering exactly what it is that a GET request exposes that a POST request doesn't?

Syed Ali hassan
  • 596
  • 4
  • 15
A. Murray
  • 2,571
  • 5
  • 26
  • 40

6 Answers6

116

in your return use the following:

return this.Json("you result", JsonRequestBehavior.AllowGet);
OldTrain
  • 1,712
  • 1
  • 23
  • 19
  • 7
    How does this actually answer the question of the OP? All this answer does is tell everyone how to get around the exception.. – eaglei22 Nov 28 '16 at 18:03
  • 2
    Yeah use it.. It's like try catch with an empty catch. DON'T use this guys (before you understand the risks). -1'd – sotn Feb 22 '17 at 14:23
  • 7
    It's irresponsible to tell people to ignore a security warning without at least explaining the consequences. -1 – Eduardo Wada Mar 22 '18 at 09:57
83

Say your website has a GetUser web method:

http://www.example.com/User/GetUser/32

which returns a JSON response:

{ "Name": "John Doe" }

If this method accepts only POST requests, then the content will only be returned to the browser if an AJAX request is made to http://www.example.com/User/GetUser/32 using the POST method. Note that unless you have implemented CORS, the browser will protect the data from other domains making this request to yours.

However, if you allowed GET requests then as well as making an AJAX request similar to the above with GET instead of POST, a malicious user could include your JSON in the context of their own site by using a script tag in the HTML. e.g. on www.evil.com:

<script src="http://www.example.com/User/GetUser/32"></script>

This JavaScript should be useless to www.evil.com because there should be no way of reading the object returned by your web method. However, due to bugs in old versions of browsers (e.g. Firefox 3), it is possible for JavaScript prototype objects to be redefined and make it possible for www.evil.com to read your data returned by your method. This is known as JSON Hijacking.

See this post for some methods of preventing this. However, it is not a known problem with the later versions of modern browsers (Firefox, Chrome, IE).

Community
  • 1
  • 1
SilverlightFox
  • 28,804
  • 10
  • 63
  • 132
  • 27
    Nice post, but if you include an [Authorize] tag to the controller you don't need to worry about security. Hope this code will help someone, Json(returnMsg, JsonRequestBehavior.AllowGet) – Dhanuka777 Dec 08 '14 at 07:13
  • 17
    @Dhanuka777: Not true unfortunately. [CSRF](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29) attacks could be possible if the method has side effects (e.g. `www.example.com/User/DeleteUser/32`) as the request will include the cookies neccessary for authentication as they are coming from the victim's machine. `[Authorize]` will not save you from the attack detailed here in the case of a very old browser either - it is the user themselves visiting `www.evil.com` so the request `www.evil.com` makes to `www.example.com` will contain the authorisation cookie. – SilverlightFox Dec 08 '14 at 11:06
  • Am I right that in case when the method does not has any side effects it is safe to just use `[Authorize]` and enable GET requests? – ps_ttf May 05 '16 at 17:19
  • @ps_ttf: If there are no side effects, [you don't need to protect the method from CSRF, although also be wary of long running requests that use up server resources](http://security.stackexchange.com/a/115826/8340). Also, due to the threat of JSON Hijacking, your approach would be vulnerable in _very old_ browsers only. – SilverlightFox May 06 '16 at 08:49
  • 2
    And if the action has any side effects it should never be invoked using the GET method — the convention is to use GET just for reading the data and all side-effecting operations should use POST, PUT, DELETE, etc. In other words, I just think that this 'sensitive information' error message is misleading. If the developer uses the GET method the way it should be used then everything is fine! :) – ps_ttf May 06 '16 at 09:01
  • @ps_ttf: It's not misleading because sensitive information could be disclosed if your site happens to support very old browsers (although you could argue users on these browsers would have other, much worse security problems to deal with). Remember that [using a non-safe method](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html) also requires that these methods have protection against CSRF. – SilverlightFox May 06 '16 at 09:16
  • 1
    I'm not sure what difference it makes still. Its not like post is any more protected or encrypted than get. It is still just plain text. I can send a request just as easily as post via any tool and still get the same plain text information back. A malicious user could just as easily write any server side code on their own site to do a post as well. – computrius Oct 11 '17 at 18:36
  • @comp. It's not about data in transit, it's about segregation of data within the browser. If evil.com can read information about your session on example.com just because you visit the former while logged into the latter then there's a problem. – SilverlightFox Oct 11 '17 at 18:40
  • Is this vulnerability not an issue if Bearer Authentication is used? – Castrohenge Dec 13 '18 at 11:26
  • 1
    @Castrohenge: No, because this requires a header to be set which won't be sent with the GET request for script src. – SilverlightFox Dec 13 '18 at 16:59
64

By default, the ASP.NET MVC framework does not allow you to respond to a GET request with a JSON payload as there is a chance a malicious user can gain access to the payload through a process known as JSON Hijacking. You do not want to return sensitive information using JSON in a GET request.

If you need to send JSON in response to a GET, and aren't exposing sensitive data, you can explicitly allow the behavior by passing JsonRequestBehavior.AllowGet as a second parameter to the Json method.

Such as

  [HttpGet] //No need to decorate, as by default it will be GET
  public JsonResult GetMyData(){  
    var myResultDataObject = buildMyData(); // build, but keep controller thin
    // delegating buildMyData to builder/Query Builder using CQRS makes easy :)
    return Json(myResultDataObject, JsonRequestBehavior.AllowGet);
  }

Here is an interesting article from Phil Haack JSON Hijacking about why not to use Json with GET method

Murali Murugesan
  • 21,303
  • 16
  • 65
  • 114
10

When we want to return a json object to client from MVC application, we should explicit specify JsonRequestBehavior.AllowGet when returning an object. As a result, I return json data as below to overcome the issue:

    return Json(yourObjectData, JsonRequestBehavior.AllowGet);
Loc Huynh
  • 266
  • 3
  • 3
6

You must be use JsonRequestBehavior.AllowGet for Json Response like this :

return Json(YourObject, JsonRequestBehavior.AllowGet);
mehdipayervand
  • 301
  • 3
  • 7
keivan kashani
  • 784
  • 8
  • 10
0

return Json("Success", JsonRequestBehavior.AllowGet)

Pergin Sheni
  • 175
  • 1
  • 11