Quelles `` informations sensibles '' pourraient être divulguées lors de la définition de JsonRequestBehavior sur AllowGet

112

J'obtiens la même vieille erreur chaque fois que je teste une nouvelle à URLpartir de la barre d'adresse de mon navigateur lorsque j'utilise returning Json(en utilisant le intégré MVC JsonResult helper):

Cette demande a été bloquée car des informations sensibles pourraient être divulguées à des sites Web tiers lorsqu'elles sont utilisées dans un fichier GET request. Pour autoriser GET requests, définissez JsonRequestBehaviorsur AllowGet.

Plutôt que de grogner en accusé de réception et de lancer Fiddler pour faire une demande de publication, cette fois, je me demande exactement ce qu'une GETdemande expose qu'une POSTdemande ne le fait pas?

A. Murray
la source

Réponses:

82

Supposons que votre site Web dispose d'une GetUserméthode Web:

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

qui renvoie une réponse JSON:

{ "Name": "John Doe" }

Si cette méthode n'accepte que les requêtes POST, le contenu ne sera renvoyé au navigateur que si une requête AJAX est effectuée à l' http://www.example.com/User/GetUser/32aide de la méthode POST. Notez qu'à moins que vous n'ayez implémenté CORS , le navigateur protégera les données des autres domaines faisant cette demande au vôtre.

Cependant, si vous avez autorisé les requêtes GET à ce moment-là et que vous faites une requête AJAX similaire à celle ci-dessus avec GET au lieu de POST, un utilisateur malveillant pourrait inclure votre JSON dans le contexte de son propre site en utilisant une scriptbalise dans le HTML. par exemple sur www.evil.com:

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

Ce JavaScript devrait être inutile www.evil.comcar il ne devrait y avoir aucun moyen de lire l'objet retourné par votre méthode web. Cependant, en raison de bugs dans les anciennes versions de navigateurs (ex: Firefox 3), il est possible que des objets prototypes JavaScript soient redéfinis et permettent www.evil.comde lire vos données renvoyées par votre méthode. C'est ce qu'on appelle le détournement JSON.

Voir cet article pour quelques méthodes pour éviter cela. Cependant, ce n'est pas un problème connu avec les dernières versions des navigateurs modernes (Firefox, Chrome, IE).

SilverlightFox
la source
25
Beau message, mais si vous incluez une balise [Authorize] dans le contrôleur, vous n'avez pas à vous soucier de la sécurité. J'espère que ce code aidera quelqu'un, Json (returnMsg, JsonRequestBehavior.AllowGet)
Dhanuka777
17
@ Dhanuka777: Pas vrai malheureusement. Les attaques CSRF pourraient être possibles si la méthode a des effets secondaires (par exemple www.example.com/User/DeleteUser/32) car la demande inclura les cookies nécessaires à l'authentification car ils proviennent de la machine de la victime. [Authorize]ne sauvera pas vous de l'attaque détaillée ici dans le cas d'un navigateur très ancien , soit - il est l'utilisateur se rendant www.evil.comsi la demande www.evil.comfait de www.example.comcontiendra le cookie d'autorisation.
SilverlightFox
1
Et si l'action a des effets secondaires, elle ne doit jamais être invoquée à l'aide de la méthode GET - la convention est d'utiliser GET uniquement pour lire les données et toutes les opérations à effet secondaire doivent utiliser POST, PUT, DELETE, etc. En d'autres termes, je pensez simplement que ce message d'erreur «informations sensibles» est trompeur. Si le développeur utilise la méthode GET comme elle doit être utilisée, tout va bien! :)
ps_ttf
1
Je ne sais pas encore quelle différence cela fait. Ce n'est pas comme si la publication était plus protégée ou cryptée que celle obtenue. Ce n'est encore que du texte brut. Je peux envoyer une demande aussi facilement que la poste via n'importe quel outil et toujours récupérer les mêmes informations en texte brut. Un utilisateur malveillant pourrait tout aussi facilement écrire n'importe quel code côté serveur sur son propre site pour publier également un message.
computrius
1
@Castrohenge: Non, car cela nécessite la définition d'un en-tête qui ne sera pas envoyé avec la requête GET pour le script src.
SilverlightFox
111

dans votre retour, utilisez les éléments suivants:

return this.Json("you result", JsonRequestBehavior.AllowGet);
OldTrain
la source
7
Comment cela répond-il réellement à la question du PO? Tout ce que cette réponse fait, c'est dire à tout le monde comment contourner l'exception ..
eaglei22
2
Ouais, utilisez-le. C'est comme essayer de prendre avec une prise vide. NE PAS utiliser ces gars (avant de comprendre les risques). -1'd
sotn le
6
Il est irresponsable de dire aux gens d'ignorer un avertissement de sécurité sans au moins en expliquer les conséquences. -1
Eduardo Wada
58

Par défaut, le framework ASP.NET MVC ne vous permet pas de répondre à une requête GET avec une charge utile JSON car il y a une chance qu'un utilisateur malveillant puisse accéder à la charge utile via un processus connu sous le nom de piratage JSON. Vous ne souhaitez pas renvoyer d'informations sensibles à l'aide de JSON dans une requête GET.

Si vous avez besoin d'envoyer JSON en réponse à un GET et que vous n'exposez pas de données sensibles, vous pouvez explicitement autoriser le comportement en le passant JsonRequestBehavior.AllowGetcomme deuxième paramètre à la Json méthode.

Tel que

  [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);
  }

Voici un article intéressant de Phil Haack JSON Hijackingsur pourquoi ne pas utiliser Json avec la méthode GET

Murali Murugesan
la source
2
Très bonne publication. Bonne raison pour laquelle vous devriez utiliser HTTPS.
pqsk
6
Je ne pense pas que HTTPS aide ici.
Sean McMillan
10

Lorsque nous voulons renvoyer un objet json au client à partir de l'application MVC, nous devons spécifier explicitement JsonRequestBehavior.AllowGet lors du retour d'un objet. En conséquence, je renvoie les données json comme ci-dessous pour résoudre le problème:

    return Json(yourObjectData, JsonRequestBehavior.AllowGet);
Loc Huynh
la source
7

Vous devez utiliser JsonRequestBehavior.AllowGet pour Json Response comme ceci:

return Json(YourObject, JsonRequestBehavior.AllowGet);
keivan kashani
la source
0

return Json ("Success", JsonRequestBehavior.AllowGet)

Pergin Sheni
la source