Quais 'informações confidenciais' podem ser divulgadas ao definir JsonRequestBehavior como AllowGet

112

Tenho recebido o mesmo erro de sempre toda vez que testo um novo URLna barra de endereços do meu navegador quando estou returning Json(usando o integrado MVC JsonResult helper):

Esta solicitação foi bloqueada porque informações confidenciais podem ser divulgadas a sites de terceiros quando usadas em a GET request. Para permitir GET requests, defina JsonRequestBehaviorcomo AllowGet.

Em vez de grunhir em reconhecimento e ativar o Fiddler para fazer uma solicitação de postagem, desta vez, estou me perguntando exatamente o que uma GETsolicitação expõe e outra POSTnão?

A. Murray
fonte

Respostas:

82

Digamos que seu site tenha um GetUsermétodo da web:

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

que retorna uma resposta JSON:

{ "Name": "John Doe" }

Se esse método aceitar apenas solicitações POST, o conteúdo só será retornado ao navegador se uma solicitação AJAX for feita http://www.example.com/User/GetUser/32usando o método POST. Observe que, a menos que você tenha implementado o CORS , o navegador protegerá os dados de outros domínios que fazem essa solicitação ao seu.

No entanto, se você permitir solicitações GET, além de fazer uma solicitação AJAX semelhante à anterior com GET em vez de POST, um usuário mal-intencionado pode incluir seu JSON no contexto de seu próprio site usando uma scripttag no HTML. por exemplo em www.evil.com:

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

Este JavaScript deve ser inútil www.evil.comporque não deve haver nenhuma maneira de ler o objeto retornado pelo seu método da web. Porém, devido a bugs em versões antigas de navegadores (por exemplo, Firefox 3), é possível redefinir objetos de protótipo JavaScript e possibilitar www.evil.coma leitura dos dados retornados pelo método. Isso é conhecido como JSON Hijacking.

Veja esta postagem para alguns métodos de prevenir isso. No entanto, não é um problema conhecido com as versões posteriores dos navegadores modernos (Firefox, Chrome, IE).

SilverlightFox
fonte
25
Boa postagem, mas se você incluir uma tag [Autorizar] no controlador, não precisa se preocupar com a segurança. Espero que este código ajude alguém, Json (returnMsg, JsonRequestBehavior.AllowGet)
Dhanuka777
17
@ Dhanuka777: Infelizmente, não é verdade. Ataques CSRF podem ser possíveis se o método tiver efeitos colaterais (por exemplo www.example.com/User/DeleteUser/32), já que a solicitação incluirá os cookies necessários para autenticação, pois eles vêm da máquina da vítima. [Authorize]não irá salvá-lo do ataque detalhado aqui no caso de um navegador muito antigo - é o próprio usuário que está visitando, www.evil.comentão a solicitação feita www.evil.compara www.example.comconterá o cookie de autorização.
SilverlightFox
1
E se a ação tiver quaisquer efeitos colaterais, ela nunca deve ser invocada usando o método GET - a convenção é usar GET apenas para ler os dados e todas as operações de efeito colateral devem usar POST, PUT, DELETE, etc. Em outras palavras, apenas pense que essa mensagem de erro de 'informações confidenciais' é enganosa. Se o desenvolvedor usar o método GET da maneira como deve ser usado, está tudo bem! :)
ps_ttf
1
Não tenho certeza da diferença que ainda faz. Não é como se a postagem fosse mais protegida ou criptografada do que qualquer outra. Ainda é apenas texto simples. Posso enviar uma solicitação tão facilmente quanto postar por meio de qualquer ferramenta e ainda obter as mesmas informações em texto simples. Um usuário mal-intencionado poderia facilmente escrever qualquer código do lado do servidor em seu próprio site para fazer uma postagem também.
computrius
1
@Castrohenge: Não, porque requer a configuração de um cabeçalho que não será enviado com a solicitação GET para script src.
SilverlightFox
111

em seu retorno, use o seguinte:

return this.Json("you result", JsonRequestBehavior.AllowGet);
OldTrain
fonte
7
Como isso realmente responde à pergunta do OP? Tudo o que esta resposta faz é dizer a todos como contornar a exceção ..
eaglei22
2
Sim, use .. É como tentar pegar com uma captura vazia. NÃO use esses caras (antes de entender os riscos). -1'd
sotn
6
É irresponsável dizer às pessoas que ignorem um aviso de segurança sem pelo menos explicar as consequências. -1
Eduardo Wada
58

Por padrão, a estrutura ASP.NET MVC não permite que você responda a uma solicitação GET com uma carga JSON, pois há uma chance de um usuário mal-intencionado obter acesso à carga por meio de um processo conhecido como JSON Hijacking. Você não deseja retornar informações confidenciais usando JSON em uma solicitação GET.

Se você precisa enviar JSON em resposta a um GET e não está expondo dados confidenciais, pode permitir explicitamente o comportamento passando JsonRequestBehavior.AllowGetcomo um segundo parâmetro para o Json método.

Tal como

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

Aqui está um artigo interessante de Phil Haack JSON Hijackingsobre por que não usar Json com o método GET

Murali Murugesan
fonte
2
Ótimo post. Boa razão para usar HTTPS.
pqsk
6
Não acho que HTTPS ajude aqui.
Sean McMillan
10

Quando queremos retornar um objeto json para o cliente do aplicativo MVC, devemos especificar explicitamente JsonRequestBehavior.AllowGet ao retornar um objeto. Como resultado, eu retorno os dados json conforme abaixo para resolver o problema:

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

Você deve usar JsonRequestBehavior.AllowGet para Resposta Json como este:

return Json(YourObject, JsonRequestBehavior.AllowGet);
Keivan Kashani
fonte
0

return Json ("Success", JsonRequestBehavior.AllowGet)

Pergin Sheni
fonte