Por que o Google precede enquanto (1); às suas respostas JSON?

Por que o Google precede while(1); às suas respostas JSON (privadas)?

Por exemplo, aqui está uma resposta ao ativar e desativar um calendar no Google Agenda :

 while(1);[['u',[['smsSentFlag','false'],['hideInvitations','false'], ['remindOnRespondedEventsOnly','true'], ['hideInvitations_remindOnRespondedEventsOnly','false_true'], ['Calendar ID stripped for privacy','false'],['smsVerifiedFlag','true']]]] 

Eu diria que isso é para impedir que as pessoas façam um eval() sobre ele, mas tudo que você realmente tem que fazer é replace o while e, em seguida, você seria definido. Eu diria que a prevenção eval é para garantir que as pessoas escrevam código JSON de análise seguro.

Eu já vi isso usado em alguns outros lugares também, mas muito mais com o Google (Mail, Agenda, Contatos, etc.) Por incrível que pareça, o Google Docs começa com &&&START&&& , e o Google Contacts parece começar com while(1); &&&START&&& while(1); &&&START&&& .

Oque esta acontecendo aqui?

Isso evita o seqüestro de JSON .

Exemplo sugerido: o Google tem um URL como mail.google.com/json?action=inbox que retorna as primeiras 50 mensagens da sua checkbox de input no formato JSON. Sites maléficos em outros domínios não podem fazer solicitações AJAX para obter esses dados devido à política de mesma origem, mas podem include o URL por meio de uma tag . A URL é visitada com seus cookies e, sobrescrevendo o construtor de matriz global ou methods de access, eles podem ter um método chamado sempre que um atributo de object (matriz ou hash) é definido, permitindo que eles leiam o conteúdo JSON.

O while(1); ou &&&BLAH&&& impede isso: uma solicitação AJAX em mail.google.com terá access total ao conteúdo de texto e poderá removê-lo. Mas uma inserção de tag executa cegamente o JavaScript sem qualquer processamento, resultando em um loop infinito ou em um erro de syntax.

Isso não aborda a questão da falsificação de solicitações entre sites .

Evita a divulgação da resposta por meio do sequestro de JSON.

Em teoria, o conteúdo das respostas HTTP é protegido pela Política de mesma origem: as páginas de um domínio não podem obter informações de páginas de outro domínio (a menos que explicitamente permitido).

Um invasor pode solicitar páginas em outros domínios em seu nome, por exemplo, usando uma tag ou , mas não pode obter informações sobre o resultado (headers, conteúdo).

Assim, se você visitar a página de um invasor, ele não poderá ler seu e-mail no gmail.com.

Exceto que, ao usar uma tag de script para solicitar conteúdo JSON, o JSON é executado como Javascript no ambiente controlado de um invasor. Se o invasor puder replace o construtor Array ou Object ou algum outro método usado durante a construção do object, qualquer coisa no JSON passará pelo código do invasor e será divulgada.

Observe que isso acontece no momento em que o JSON é executado como Javascript, não no momento em que é analisado.

Existem várias contra-medidas:

Certificando-se de que o JSON nunca execute

Colocando um while(1); declaração antes dos dados JSON, o Google garante que os dados JSON nunca sejam executados como Javascript.

Apenas uma página legítima pode realmente obter todo o conteúdo, tira o while(1); e analise o restante como JSON.

Coisas como for(;;); foram vistos no Facebook, por exemplo, com os mesmos resultados.

Certificando-se de que o JSON não é um Javascript válido

Da mesma forma, adicionar tokens inválidos antes do JSON, como &&&START&&& , garante que ele nunca seja executado.

Sempre retorne JSON com um object do lado de fora

Essa é a maneira recomendada pelo OWASP de proteger contra o seqüestro de JSON e é a menos intrusiva.

Similarmente às contra-medidas anteriores, garante que o JSON nunca seja executado como Javascript.

Um object JSON válido, quando não incluído por nada, não é válido em Javascript:

 eval('{"foo":"bar"}') // SyntaxError: Unexpected token : 

No entanto, este é um JSON válido:

 JSON.parse('{"foo":"bar"}') // Object {foo: "bar"} 

Portanto, certificar-se de sempre retornar um Objeto no nível superior da resposta garante que o JSON não seja um Javascript válido, embora ainda seja válido como JSON.

Como observado por @hvd nos comentários, o object vazio {} é um Javascript válido, e saber que o object está vazio pode ser uma informação valiosa.

Comparação dos methods acima

O caminho OWASP é menos intrusivo, pois não precisa de alterações na biblioteca do cliente e transfere o JSON válido. Não tem certeza se os erros passados ​​ou futuros do navegador podem derrotar isso, no entanto. Como observado por @oriadam, não está claro se os dados podem ser vazados em um erro de análise através de um tratamento de erros ou não (por exemplo, window.onerror).

A maneira do Google requer uma biblioteca de clientes para que ela suporte a desserialização automática e pode ser considerada mais segura em relação aos bugs do navegador.

Ambos os methods exigem alterações no lado do servidor para evitar que os desenvolvedores enviem acidentalmente JSON vulnerável.

Isso é para garantir que algum outro site não possa fazer truques desagradáveis ​​para tentar roubar seus dados. Por exemplo, substituindo o construtor de matriz , incluindo essa URL JSON por meio de uma tag , um site de terceiros mal-intencionado poderia roubar os dados da resposta JSON. Colocando um while(1); no começo, o script irá travar.

Por outro lado, uma solicitação no mesmo site usando XHR e um analisador JSON separado pode facilmente ignorar o while(1); prefixo.

Isso tornaria difícil para um terceiro inserir a resposta JSON em um documento HTML com a tag . Lembre-se de que a tag está isenta da Política de mesma origem .

Isso impede que ele seja usado como o destino de uma tag simples. (Bem, isso não impede, mas torna desagradável.) Dessa forma, os caras mal-intencionados não podem simplesmente colocar essa tag de script em seu próprio site e confiar em uma session ativa para tornar possível buscar seu conteúdo.

edit - anote o comentário (e outras respostas). O problema tem a ver com resources embutidos subvertidos, especificamente os construtores Object e Array . Essas podem ser alteradas de forma que o JSON, que é inofensivo quando analisado, possa acionar o código do invasor.

Como a tag está isenta da Política de mesma origem, que é uma necessidade de segurança no mundo da web, while(1) quando adicionada à resposta JSON impede o uso indevido dela na tag .

Esta é uma correção para um ataque antigo. 95,2% dos usuários de internet agora são corrigidos contra

while(1) , for(;;) injeção foram todas destinadas a evitar ataques de seqüestro JSON, onde replace internals Javascript iria permitir que um invasor solicitar dados, digamos, google.com, carregando a resposta JSON como Javascript. Com essas correções, o loop infinito faria com que o JSON nunca executasse e suspendesse o navegador.

É importante observar que isso foi corrigido desde o ECMA5 (2009), que especificou que a análise de array e object só usaria o construtor integrado, evitando esse ataque. O Facebook, o Google e outros grandes players às vezes ainda os têm por vários motivos, incluindo que eles vêm de APIs legadas, que possuem bibliotecas maduras que lidam com esse aspecto legado da análise JSON e que, em alguns casos, têm suporte a nicho, desatualizado navegadores.

O último grande navegador a implementar o ECMA5 foi o IE 9, em 2011 [ver compat. tabela ] e agora é suportado por 95,57% de todo o tráfego da Internet (95,52% no desktop, 100% no celular).

Se você está criando uma API nos dias de hoje, isso não deve ser algo com o qual você precise se preocupar. Em 2018, é muito mais eficaz usar Access-Control-Allow-Origin: * (que é bastante seguro por padrão) e esperar autenticação baseada em header de autorização (geralmente Authorization: oauth [token] ), que na maioria dos aplicativos impede esse tipo roubo de origem cruzada e CSRF (já que o invasor só pode afetar a conta para a qual está autorizado).

Isso não, como alguns postaram correção CSRF. A solicitação ainda é autorizada pelos cookies da vítima, mesmo que eles não possam ver a resposta.