Perché Google antepone mentre (1); alle loro risposte JSON?


4078

Perché Google antepone while(1);alle loro risposte (private) JSON?

Ad esempio, ecco una risposta durante l'attivazione e la disattivazione di un calendario in Google Calendar :

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

Suppongo che questo sia per impedire alle persone eval()di farne uno , ma tutto ciò che dovresti fare è sostituire il whilee poi verrai impostato. Suppongo che la prevenzione eval sia quella di assicurarsi che le persone scrivano un codice di analisi JSON sicuro.

L'ho visto usato anche in un paio di altri posti, ma molto di più con Google (Mail, Calendar, Contacts, ecc.) Stranamente, Google Docs inizia &&&START&&&invece e Google Contacts sembra iniziare while(1); &&&START&&&.

Cosa sta succedendo qui?


45
Credo che la tua prima impressione sia corretta. Se inizi a cercare il codice e provi a tagliare il flusso di input in base alla fonte, riconsidereresti e lo faresti nel modo più sicuro (e grazie alle azioni di Google, più semplice).
Esteban Küber,

34
probabilmente una domanda di follow-up: perché Google antepone )]}'ora invece di while(1);? Le risposte sarebbero le stesse?
Gizmo,

3
Eviterebbe eval, ma non con un ciclo infinito.
Mardoxx,

9
Questo )]}'potrebbe anche essere per salvare byte, come Facebook utilizzato for(;;);che salva un byte :)
Gras Double

3
Inorder per impedire la divulgazione di json cioèJSON hijacking
Ashraf.Shk786

Risposte:


4293

Previene il dirottamento JSON , un grave problema di sicurezza JSON che è stato risolto formalmente in tutti i principali browser dal 2011 con ECMAScript 5.

Esempio contrastato: supponiamo che Google abbia un URL simile a quello mail.google.com/json?action=inboxche restituisce i primi 50 messaggi della posta in arrivo in formato JSON. I siti Web malvagi su altri domini non possono effettuare richieste AJAX per ottenere questi dati a causa della stessa politica di origine, ma possono includere l'URL tramite un <script>tag. L'URL viene visitato con i tuoi cookie e sovrascrivendo il costruttore globale dell'array o i metodi di accesso possono avere un metodo chiamato ogni volta che viene impostato un attributo oggetto (array o hash), che consente loro di leggere il contenuto JSON.

Il while(1);o &&&BLAH&&&impedisce questo: una richiesta AJAX a mail.google.comavrà pieno accesso al contenuto del testo e può eliminarlo. Ma un <script>inserimento di tag esegue ciecamente JavaScript senza alcuna elaborazione, causando un ciclo infinito o un errore di sintassi.

Ciò non risolve il problema della falsificazione delle richieste tra siti .


228
Perché la richiesta di ottenere questi dati non richiede invece un token CSRF?
Jakub P.

235
Fa for(;;);lo stesso lavoro? Ho visto questo nelle risposte ajax di Facebook.
Re Julien,

183
@JakubP. La memorizzazione e la manutenzione dei token CSRF su scala di Google richiede una grande quantità di infrastrutture e costi.
Abraham,

127
@JakubP. I token anti-CSRF pasticciano con la memorizzazione nella cache e richiedono una certa quantità di valutazione crittografica lato server. Su scala di Google, ciò richiederebbe molta CPU. Questo tipo di viene scaricato sul client.
bluesmoon,

96
Mi sembra che un modo migliore sarebbe lasciare che il server invii il JSON solo se è stata impostata l'intestazione corretta. Puoi farlo in una chiamata AJAX, ma non con i tag di script. In questo modo, le informazioni sensibili non vengono nemmeno inviate e non è necessario fare affidamento sulla sicurezza lato browser.
mcv,

574

Impedisce la divulgazione della risposta tramite il dirottamento JSON.

In teoria, il contenuto delle risposte HTTP è protetto dalla stessa politica di origine: le pagine di un dominio non possono ottenere alcuna informazione dalle pagine dell'altro dominio (se non esplicitamente consentito).

Un utente malintenzionato può richiedere pagine su altri domini per conto dell'utente, ad esempio utilizzando un tag <script src=...>o <img>, ma non può ottenere alcuna informazione sul risultato (intestazioni, contenuti).

Pertanto, se visiti la pagina di un utente malintenzionato, non è in grado di leggere la tua email da gmail.com.

Tranne il fatto che quando si utilizza un tag di script per richiedere il contenuto JSON, il JSON viene eseguito come Javascript nell'ambiente controllato di un utente malintenzionato. Se l'attaccante può sostituire il costruttore di array o oggetti o qualche altro metodo utilizzato durante la costruzione di oggetti, qualsiasi cosa nel JSON passerebbe attraverso il codice dell'attaccante e verrebbe divulgata.

Si noti che ciò accade nel momento in cui JSON viene eseguito come Javascript, non nel momento in cui viene analizzato.

Esistono diverse contromisure:

Assicurarsi che JSON non venga mai eseguito

Inserendo una while(1);dichiarazione prima dei dati JSON, Google si assicura che i dati JSON non vengano mai eseguiti come Javascript.

Solo una pagina legittima può ottenere l'intero contenuto, eliminare il file while(1);e analizzare il resto come JSON.

Cose come for(;;);sono state viste su Facebook per esempio, con gli stessi risultati.

Assicurarsi che JSON non sia Javascript valido

Allo stesso modo, l'aggiunta di token non validi prima del JSON, come &&&START&&&, assicura che non venga mai eseguito.

Restituisce sempre JSON con un oggetto all'esterno

Questo è il OWASPmodo consigliato per proteggere dal dirottamento JSON ed è quello meno invadente.

Simile alle precedenti contromisure, si assicura che JSON non venga mai eseguito come Javascript.

Un oggetto JSON valido, quando non è racchiuso tra nulla, non è valido in Javascript:

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

Questo è comunque valido JSON:

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

Quindi, assicurati di restituire sempre un oggetto al livello più alto della risposta assicurandoti che JSON non sia Javascript valido, pur essendo comunque JSON valido.

Come notato da @hvd nei commenti, l'oggetto vuoto {}è Javascript valido e sapere che l'oggetto è vuoto può essere essa stessa un'informazione preziosa.

Confronto dei metodi sopra indicati

Il modo OWASP è meno invadente, in quanto non necessita di modifiche alla libreria client e trasferisce JSON valido. Non è sicuro, tuttavia, se i bug passati o futuri del browser potrebbero sconfiggere questo. Come notato da @oriadam, non è chiaro se i dati potrebbero essere trapelati in un errore di analisi attraverso una gestione degli errori o meno (ad esempio window.onerror).

Per Google è necessario che la libreria client supporti la deserializzazione automatica e può essere considerata più sicura riguardo ai bug del browser.

Entrambi i metodi richiedono modifiche sul lato server per evitare agli sviluppatori di inviare accidentalmente JSON vulnerabile.


23
La raccomandazione OWASP è interessante per la sua semplicità. Qualcuno sa un motivo per cui la strada di Google è più sicura?
funroll

18
Credo che non sia più sicuro in alcun modo. Fornire OWASP qui sembra un motivo sufficiente per +1.

30
Vale la pena notare perché la restituzione di un oggetto letterale non riesce con il scripttag o la evalfunzione. Le parentesi graffe {}possono essere interpretate come un blocco di codice o un oggetto letterale e, di per sé, JavaScript preferisce il primo. Come blocco di codice, ovviamente, non è valido. In base a questa logica, non riesco a vedere alcun cambiamento prevedibile nel futuro comportamento del browser.
Manngo,

16
Il codice errato non è sufficiente perché un utente malintenzionato può anche dirottare l'hander di errori di script del browser ( window.onerror) Non sono sicuro di quale sia il comportamento degli onerrorerrori di sintassi. Immagino che anche Google non fosse sicuro.
Oriadam,

12
"Un oggetto JSON valido, quando non è racchiuso tra niente, non è valido in Javascript:" - Tranne il caso banale di un oggetto vuoto ( {}), che è anche un blocco vuoto valido. Se la conoscenza dell'oggetto è vuota può essere essa stessa un'informazione preziosa, questa può essere sfruttabile.

371

Questo per garantire che altri siti non possano fare brutti scherzi per tentare di rubare i tuoi dati. Ad esempio, sostituendo il costruttore di array , quindi includendo questo URL JSON tramite un <script>tag, un sito di terze parti dannoso potrebbe rubare i dati dalla risposta JSON. Mettendo while(1);a all'inizio, lo script si bloccherà invece.

Una richiesta dello stesso sito che utilizza XHR e un parser JSON separato, d'altra parte, può facilmente ignorare il while(1);prefisso.


6
Tecnicamente, un parser JSON "normale" dovrebbe dare un errore se si dispone di un prefisso.
Matthew Crumley,

12
Gli aggressori userebbero semplicemente un vecchio <script>elemento, non un XHR.
Laurence Gonsalves,

9
@Matthew, certo, ma puoi rimuoverlo prima di passare i dati al parser JSON. Non puoi farlo con un <script>tag
bdonlan

7
Ci sono esempi di questo? La sostituzione del costruttore di array è di nuovo referenziata, ma si tratta di un bug risolto da tempo. Non capisco come si possa avere accesso ai dati ricevuti tramite il tag script. Mi piacerebbe vedere un'implementazione fittizia che funziona nel browser recente.
Dennis G,

7
@joeltine, no, non lo è. Vedi stackoverflow.com/questions/16289894/… .

111

Ciò significherebbe rendere difficile per una terza parte inserire la risposta JSON in un documento HTML con il <script>tag. Ricorda che il <script>tag è esente dalla stessa politica di origine .


21
Questa è solo una mezza risposta. Se non fosse per il trucco di scavalcare i costruttori Objecte Array, eseguire una risposta JSON valida come se fosse JavaScript sarebbe totalmente innocuo in tutte le circostanze. Sì, while(1);impedisce che la risposta venga eseguita come JavaScript se targetizzata da un <script>tag, ma la tua risposta non spiega perché sia ​​necessario.
Mark Amery,

ma come impedirà gli iframe
Ravinder Payal,

Il tag script non è mai esente dalla stessa politica di origine. Potresti chiarirlo per me?
Suraj Jain,

82

Nota : a partire dal 2019, molte delle vecchie vulnerabilità che portano alle misure preventive discusse in questa domanda non sono più un problema nei browser moderni. Lascerò la risposta di seguito come una curiosità storica, ma in realtà l'intero argomento è cambiato radicalmente dal 2010 (!!) quando è stato chiesto.


Impedisce che venga utilizzato come target di un semplice <script>tag. (Beh, non lo impedisce, ma lo rende spiacevole.) In questo modo i cattivi non possono semplicemente mettere quel tag di script nel proprio sito e fare affidamento su una sessione attiva per consentire di recuperare i tuoi contenuti.

modifica - annota il commento (e altre risposte). Il problema riguarda le strutture integrate sovvertite, in particolare i costruttori Objecte Array. Questi possono essere modificati in modo tale che JSON altrimenti innocuo, una volta analizzato, possa innescare il codice dell'attaccante.


17
Questa è solo una mezza risposta. Se non fosse per il trucco di scavalcare i costruttori Objecte Array, eseguire una risposta JSON valida come se fosse JavaScript sarebbe totalmente innocuo in tutte le circostanze. Sì, while(1);impedisce che la risposta venga eseguita come JavaScript se targetizzata da un <script>tag, ma la tua risposta non spiega perché sia ​​necessario.
Mark Amery,

11

Poiché il <script>tag è esentato dalla stessa politica di origine che è una necessità di sicurezza nel mondo web, while(1)quando aggiunto alla risposta JSON ne impedisce l'uso improprio nel <script>tag.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.