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

4077

Por que o Google anexa while(1);suas respostas JSON (privadas)?

Por exemplo, aqui está uma resposta ao ativar e desativar um calendário 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 eval()algo, mas tudo o que você realmente precisa fazer é substituir o whilee, então, você estará pronto. Eu assumiria que a prevenção de avaliação é garantir que as pessoas escrevam código de análise JSON seguro.

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

O que está acontecendo aqui?

Jess
fonte
45
Acredito que sua primeira impressão esteja correta. Se você começar a procurar código e tentar cortar o fluxo de entrada, dependendo da fonte, reconsidere e faça da maneira segura (e por causa das ações do Google, mais fácil).
Esteban Küber 19/04/10
34
provavelmente uma pergunta de acompanhamento: por que o Google precede )]}'agora agora em vez de while(1);? As respostas seriam as mesmas?
Gizmo
3
Impediria eval, mas não com um loop infinito.
Mardoxx 6/06
9
Esta )]}'também pode ser a de salvar bytes, como facebook usado for(;;);o que economiza um byte :)
Gras Duplo
3
Inorder para impedir a divulgação de json ou sejaJSON hijacking
Ashraf.Shk786

Respostas:

4293

Impede o seqüestro de JSON , um grande problema de segurança JSON formalmente corrigido em todos os principais navegadores desde 2011 com o ECMAScript 5.

Exemplo artificial: digamos que o Google tenha um URL como o mail.google.com/json?action=inboxque retorna as primeiras 50 mensagens da sua caixa de entrada no formato JSON. Sites mal-intencionados em outros domínios não podem fazer solicitações AJAX para obter esses dados devido à política de mesma origem, mas podem incluir o URL por meio de uma <script>tag. A URL é visitada com seus cookies e, substituindo os métodos de construtor ou acessador de matriz global, eles podem ter um método chamado sempre que um atributo de objeto (matriz ou hash) for definido, permitindo que eles leiam o conteúdo JSON.

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

Isso não resolve o problema de falsificação de solicitação entre sites .

rjh
fonte
228
Por que a solicitação para obter esses dados não requer um token CSRF?
Jakub P.
235
Faz for(;;);o mesmo trabalho? Eu já vi isso nas respostas ajax do facebook.
Julien King
183
@JakubP. Armazenar e manter tokens de CSRF na escala do Google requer uma grande quantidade de infraestrutura e custo.
Abraham
127
@JakubP. os tokens anti-CSRF interferem no cache e exigem uma certa quantidade de avaliação criptográfica no lado do servidor. Na escala do Google, isso exigiria muita CPU. Esse tipo de descarrega para o cliente.
Bluesmoon
96
Parece-me que uma maneira melhor seria permitir que o servidor envie apenas o JSON se o cabeçalho correto tiver sido definido. Você pode fazer isso em uma chamada AJAX, mas não com tags de script. Dessa forma, as informações confidenciais nunca são enviadas e você não precisa confiar na segurança do navegador.
Mcv
574

Impede a divulgação da resposta por meio do seqüestro de JSON.

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

Um invasor pode solicitar páginas em outros domínios em seu nome, por exemplo, usando uma tag <script src=...>ou <img>, mas não pode obter nenhuma informação sobre o resultado (cabeçalhos, conteúdo).

Portanto, se você visitar a página de um invasor, ele não poderá ler seu email 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 atacante puder substituir o construtor Array ou Object ou algum outro método usado durante a construção do objeto, 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 contramedidas:

Garantindo que o JSON nunca execute

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

Somente uma página legítima poderia obter todo o conteúdo, remover while(1);e analisar o restante como JSON.

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

Certificando-se de que o JSON não é 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 objeto do lado de fora

Essa é a OWASPmaneira recomendada de proteger contra o seqüestro de JSON e é a menos invasiva.

Semelhante às contramedidas anteriores, garante que o JSON nunca seja executado como Javascript.

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

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

No entanto, isto é JSON válido:

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

Portanto, sempre retorne um Objeto no nível superior da resposta para garantir que o JSON não seja Javascript válido, enquanto ainda é JSON válido.

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

Comparação dos métodos acima

A maneira OWASP é menos invasiva, pois não precisa de alterações na biblioteca do cliente e transfere JSON válido. No entanto, não é certo se os erros anteriores ou futuros do navegador podem anular isso. Como observado por @oriadam, não está claro se os dados podem ter vazado em um erro de análise através de um tratamento de erros ou não (por exemplo, window.onerror).

A maneira do Google exige que a biblioteca do cliente suporte a desserialização automática e pode ser considerada mais segura em relação aos bugs do navegador.

Ambos os métodos exigem alterações no servidor para evitar que os desenvolvedores enviem acidentalmente JSON vulnerável.

Arnaud Le Blanc
fonte
23
A recomendação da OWASP é interessante devido à sua simplicidade. Alguém sabe um motivo pelo qual o caminho do Google é mais seguro?
funroll
18
Eu acredito que não é mais seguro de forma alguma. Fornecer OWASP aqui parece uma razão boa o suficiente para +1.
30
Pode ser interessante notar por que o retorno de um literal de objeto falha na scripttag ou na evalfunção. Os colchetes {}podem ser interpretados como um bloco de código ou um objeto literal e, por si só, o JavaScript prefere o anterior. Como um bloco de código, é claro que é inválido. Por essa lógica, não vejo alterações previsíveis no comportamento futuro do navegador.
Manngo
16
Um código incorreto não é suficiente porque um invasor também pode seqüestrar o manipulador de erros de script do navegador ( window.onerror) Não sei ao certo qual é o comportamento dos onerrorerros de sintaxe. Acho que o Google também não tinha certeza.
oriadam 6/12/15
12
"Um objeto JSON válido, quando não está incluído em nada, não é válido em Javascript:" - Exceto no caso trivial de um objeto vazio ( {}), que também é um bloco vazio válido. Se saber que o objeto está vazio pode ser uma informação valiosa, isso pode ser explorável.
371

Isso é para garantir que outro site não possa fazer truques desagradáveis ​​para tentar roubar seus dados. Por exemplo, substituindo o construtor da matriz e incluindo essa URL JSON por meio de uma <script>tag, um site de terceiros mal-intencionado pode roubar os dados da resposta JSON. Ao colocar um while(1);no início, o script travará.

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

bdonlan
fonte
6
Tecnicamente, um analisador JSON "normal" deve gerar um erro se você tiver um prefixo.
Matthew Crumley
12
Os atacantes usariam apenas um <script>elemento antigo simples , não um XHR.
Laurence Gonsalves
9
@ Matthew, claro, mas você pode removê-lo antes de passar os dados para o analisador JSON. Você não pode fazer isso com uma <script>tag
bdonlan
7
Existem exemplos disso? A substituição do construtor da matriz é referenciada novamente, mas esse erro foi corrigido por muito tempo. Não entendo como alguém teria acesso aos dados recebidos por meio da tag de script. Eu adoraria ver uma implementação fictícia que funciona no navegador recente.
Dennis L
7
@joeltine, não, não é. Consulte stackoverflow.com/questions/16289894/… .
111

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

Daniel Vassallo
fonte
21
Isso é apenas meia resposta. Se não fosse o truque de substituir os construtores Objecte Array, executar uma resposta JSON válida como se fosse JavaScript seria totalmente inócuo em todas as circunstâncias. Sim, isso while(1);impede que a resposta seja executada como JavaScript se for direcionada por uma <script>tag, mas sua resposta não explica por que isso é necessário.
Mark Amery
mas como ele irá impedir iframe
Ravinder Payal
A tag de script nunca é isenta da mesma política de origem. Você poderia esclarecer isso para mim?
Suraj Jain # /
82

Nota : a partir de 2019, muitas das vulnerabilidades antigas que levam às medidas preventivas discutidas nesta pergunta não são mais um problema nos navegadores modernos. Deixarei a resposta abaixo como uma curiosidade histórica, mas realmente todo o tópico mudou radicalmente desde 2010 (!!), quando isso foi perguntado.


Impede que seja usado como alvo de uma <script>tag simples . (Bem, isso não a impede, mas a torna desagradável.) Dessa forma, os bandidos não podem simplesmente colocar essa tag de script em seu próprio site e confiar em uma sessão ativa para tornar possível a busca do seu conteúdo.

editar - observe o comentário (e outras respostas). A questão tem a ver com instalações internas subvertidas, especificamente os construtores Objecte Array. Elas podem ser alteradas de forma que, caso contrário, o JSON inócuo, quando analisado, possa acionar o código do invasor.

Pontudo
fonte
17
Isso é apenas meia resposta. Se não fosse o truque de substituir os construtores Objecte Array, executar uma resposta JSON válida como se fosse JavaScript seria totalmente inócuo em todas as circunstâncias. Sim, isso while(1);impede que a resposta seja executada como JavaScript se for direcionada por uma <script>tag, mas sua resposta não explica por que isso é necessário.
Mark Amery
11

Como a <script>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, evita o uso indevido dela na <script>tag.

Krishna Ganeriwal
fonte