Warum stellt Google während (1) voran? auf ihre JSON-Antworten?

4076

Warum stellt Google while(1);seinen (privaten) JSON-Antworten voran?

Hier ist beispielsweise eine Antwort beim Ein- und Ausschalten eines Kalenders in Google Kalender :

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

Ich würde annehmen, dass dies dazu dient, Leute daran zu hindern, etwas zu tun eval(), aber alles, was Sie wirklich tun müssten, ist das zu ersetzen whileund dann wären Sie eingestellt. Ich würde annehmen, dass die Eval-Prävention darin besteht, sicherzustellen, dass die Leute sicheren JSON-Parsing-Code schreiben.

Ich habe gesehen, dass dies auch an einigen anderen Orten verwendet wird, aber viel mehr bei Google (E-Mail, Kalender, Kontakte usw.). Seltsamerweise beginnt Google Text&&&START&&& & Tabellen stattdessen mit und Google Kontakte scheint damit zu beginnen while(1); &&&START&&&.

Was ist denn hier los?

Jess
quelle
45
Ich glaube, dass Ihr erster Eindruck richtig ist. Wenn Sie nach Code suchen und versuchen, den Eingabestream abhängig von der Quelle zu kürzen, überdenken Sie dies und tun dies auf sichere (und aufgrund der Aktionen von Google einfacher) Weise.
Esteban Küber
34
wahrscheinlich eine Folgefrage: Warum stellt Google )]}'jetzt statt statt while(1);? Wären die Antworten gleich?
Gizmo
3
Würde eval verhindern, aber nicht mit einer Endlosschleife.
Mardoxx
9
Dies )]}'kann auch sein, um Bytes zu speichern, wie Facebook verwendet, for(;;);das ein Byte speichert :)
Gras Double
3
Um die Offenlegung von json zu verhindern, dhJSON hijacking
Ashraf.Shk786

Antworten:

4293

Es verhindert JSON-Hijacking , ein wichtiges JSON-Sicherheitsproblem, das seit 2011 mit ECMAScript 5 in allen gängigen Browsern offiziell behoben wurde .

Erfundenes Beispiel: Angenommen, Google hat eine URL, mail.google.com/json?action=inboxdie die ersten 50 Nachrichten Ihres Posteingangs im JSON-Format zurückgibt. Böse Websites in anderen Domains können aufgrund der Richtlinie mit demselben Ursprung keine AJAX-Anfragen zum Abrufen dieser Daten stellen, sie können jedoch die URL über ein <script>Tag einschließen . Die URL wird mit Ihren Cookies besucht. Durch Überschreiben der globalen Array-Konstruktor- oder Accessor-Methoden kann eine Methode aufgerufen werden, wenn ein Objektattribut (Array oder Hash) festgelegt wird, sodass sie den JSON-Inhalt lesen können.

Das while(1);oder &&&BLAH&&&verhindert dies: Eine AJAX-Anfrage mail.google.comhat vollen Zugriff auf den Textinhalt und kann ihn entfernen. Beim <script>Einfügen von Tags wird das JavaScript jedoch blind und ohne Verarbeitung ausgeführt, was entweder zu einer Endlosschleife oder zu einem Syntaxfehler führt.

Dies betrifft nicht das Problem der Fälschung von standortübergreifenden Anfragen .

rjh
quelle
228
Warum erfordert die Anforderung, diese Daten zu erhalten, nicht stattdessen ein CSRF-Token?
Jakub P.
235
Macht for(;;);den gleichen Job? Ich habe dies in den Ajax-Antworten von Facebook gesehen.
König Julien
183
@ JakubP. Das Speichern und Verwalten von CSRF-Token in Googles Größenordnung erfordert eine große Menge an Infrastruktur und Kosten.
Abraham
127
@ JakubP. Anti-CSRF-Token beeinträchtigen das Caching und erfordern eine gewisse Menge an kryptografischer Auswertung auf der Serverseite. Bei Google würde dies viel CPU erfordern. Diese Art der Auslagerung an den Client.
Bluesmoon
96
Es scheint mir ein besserer Weg zu sein, den Server den JSON nur senden zu lassen, wenn der richtige Header gesetzt wurde. Sie können dies in einem AJAX-Aufruf tun, jedoch nicht mit Skript-Tags. Auf diese Weise werden die vertraulichen Informationen nicht einmal gesendet, und Sie müssen sich nicht auf die Sicherheit auf der Browserseite verlassen.
mcv
574

Es verhindert die Offenlegung der Antwort durch JSON-Hijacking.

Theoretisch ist der Inhalt von HTTP-Antworten durch die Richtlinie für denselben Ursprung geschützt: Seiten einer Domäne können keine Informationen von Seiten der anderen Domäne abrufen (sofern dies nicht ausdrücklich gestattet ist).

Ein Angreifer kann in Ihrem Namen Seiten in anderen Domänen anfordern, z. B. mithilfe eines Tags <script src=...>oder <img>, kann jedoch keine Informationen über das Ergebnis (Header, Inhalt) abrufen.

Wenn Sie also die Seite eines Angreifers besuchen, konnte diese Ihre E-Mail von gmail.com nicht lesen.

Wenn Sie jedoch ein Skript-Tag zum Anfordern von JSON-Inhalten verwenden, wird JSON in der kontrollierten Umgebung eines Angreifers als Javascript ausgeführt. Wenn der Angreifer den Array- oder Objektkonstruktor oder eine andere Methode ersetzen kann, die während der Objektkonstruktion verwendet wird, wird alles im JSON durch den Code des Angreifers geleitet und offengelegt.

Beachten Sie, dass dies zum Zeitpunkt der Ausführung des JSON als Javascript geschieht und nicht zum Zeitpunkt der Analyse.

Es gibt mehrere Gegenmaßnahmen:

Stellen Sie sicher, dass JSON niemals ausgeführt wird

Durch Platzieren einer while(1);Anweisung vor den JSON-Daten stellt Google sicher, dass die JSON-Daten niemals als Javascript ausgeführt werden.

Nur eine legitime Seite kann den gesamten Inhalt while(1);abrufen, den Inhalt entfernen und den Rest als JSON analysieren.

Dinge wie for(;;);zum Beispiel wurden bei Facebook gesehen, mit den gleichen Ergebnissen.

Stellen Sie sicher, dass JSON kein gültiges Javascript ist

In ähnlicher Weise wird durch Hinzufügen ungültiger Token vor dem JSON &&&START&&&sichergestellt, dass er niemals ausgeführt wird.

Geben Sie JSON immer mit einem Objekt an der Außenseite zurück

Dies wird OWASPempfohlen , um sich vor JSON-Hijacking zu schützen, und ist weniger aufdringlich.

Ähnlich wie bei den vorherigen Gegenmaßnahmen wird sichergestellt, dass der JSON niemals als Javascript ausgeführt wird.

Ein gültiges JSON-Objekt ist in Javascript nicht gültig, wenn es von nichts eingeschlossen ist:

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

Dies ist jedoch gültig JSON:

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

Stellen Sie daher sicher, dass Sie immer ein Objekt auf der obersten Ebene der Antwort zurückgeben. Stellen Sie sicher, dass JSON kein gültiges Javascript ist, während JSON weiterhin gültig ist.

Wie von @hvd in den Kommentaren angegeben, ist das leere Objekt {}gültiges Javascript, und das Wissen, dass das Objekt leer ist, kann selbst eine wertvolle Information sein.

Vergleich der obigen Methoden

Der OWASP-Weg ist weniger aufdringlich, da keine Änderungen an der Clientbibliothek erforderlich sind und gültiger JSON übertragen wird. Es ist jedoch nicht sicher, ob frühere oder zukünftige Browserfehler dies verhindern könnten. Wie von @oriadam festgestellt, ist unklar, ob bei einem Analysefehler durch eine Fehlerbehandlung Daten verloren gehen könnten oder nicht (z. B. window.onerror).

Der Weg von Google erfordert, dass die Client-Bibliothek die automatische De-Serialisierung unterstützt, und kann als sicherer in Bezug auf Browser-Fehler angesehen werden.

Beide Methoden erfordern serverseitige Änderungen, um zu verhindern, dass Entwickler versehentlich anfälliges JSON senden.

Arnaud Le Blanc
quelle
23
Die OWASP-Empfehlung ist wegen ihrer Einfachheit interessant. Kennt jemand einen Grund, warum Googles Weg sicherer ist?
Funroll
18
Ich glaube, es ist in keiner Weise sicherer. Die Bereitstellung von OWASP hier scheint ein guter Grund für +1 zu sein.
30
Es kann erwähnenswert sein, warum die Rückgabe eines Objektliteral das scriptTag oder die evalFunktion nicht erfüllt. Die geschweiften Klammern {}können entweder als Codeblock oder als Objektliteral interpretiert werden, und JavaScript selbst bevorzugt das erstere. Als Codeblock ist er natürlich ungültig. Durch diese Logik kann ich keine vorhersehbaren Änderungen im zukünftigen Browserverhalten erkennen.
Manngo
16
Schlechter Code reicht nicht aus, da ein Angreifer auch den Skriptfehler-Hander des Browsers entführen kann ( window.onerror). Ich bin mir nicht sicher, wie sich onerrorSyntaxfehler verhalten . Ich denke, Google war sich auch nicht sicher.
Oriadam
12
"Ein gültiges JSON-Objekt ist in Javascript nicht gültig, wenn es von nichts eingeschlossen ist:" - Mit Ausnahme des trivialen Falls eines leeren Objekts ( {}), das ebenfalls ein gültiger leerer Block ist. Wenn das Wissen, dass das Objekt leer ist, selbst wertvolle Informationen sein kann, kann dies ausgenutzt werden.
371

Dies soll sicherstellen, dass eine andere Site keine bösen Tricks ausführen kann, um zu versuchen, Ihre Daten zu stehlen. Wenn Sie beispielsweise den Array-Konstruktor ersetzen und diese JSON-URL über ein <script>Tag einfügen, kann eine böswillige Website eines Drittanbieters die Daten aus der JSON-Antwort stehlen. Wenn Sie while(1);am Anfang ein setzen, bleibt das Skript hängen.

Eine Anforderung an derselben Site, die XHR und einen separaten JSON-Parser verwendet, kann das while(1);Präfix leicht ignorieren .

bdonlan
quelle
6
Technisch gesehen sollte ein "normaler" JSON-Parser einen Fehler ausgeben, wenn Sie ein Präfix haben.
Matthew Crumley
12
Angreifer würden nur ein einfaches altes <script>Element verwenden, kein XHR.
Laurence Gonsalves
9
@Matthew, sicher, aber Sie können es entfernen, bevor Sie die Daten an den JSON-Parser übergeben. Sie können das nicht mit einem <script>Tag tun
bdonlan
7
Gibt es Beispiele dafür? Das Ersetzen des Array-Konstruktors wird erneut referenziert, aber das ist ein Fehler, der lange behoben wurde. Ich verstehe nicht, wie man Zugriff auf die Daten haben würde, die über das Skript-Tag empfangen werden. Ich würde gerne eine Dummy-Implementierung sehen, die im aktuellen Browser funktioniert.
Dennis G
7
@joeltine, nein, ist es nicht. Siehe stackoverflow.com/questions/16289894/… .
111

Dies würde es einem Drittanbieter erschweren, die JSON-Antwort mit dem <script>Tag in ein HTML-Dokument einzufügen . Beachten Sie, dass das <script>Tag von der Richtlinie für denselben Ursprung ausgenommen ist .

Daniel Vassallo
quelle
21
Dies ist nur eine halbe Antwort. Ohne den Trick, die Konstruktoren Objectund zu überschreiben Array, wäre es unter allen Umständen völlig harmlos, eine gültige JSON-Antwort so auszuführen, als wäre es JavaScript. Ja, das while(1);verhindert , dass die Antwort als JavaScript ausgeführt wird, wenn sie von einem <script>Tag als Ziel ausgewählt wird. Ihre Antwort erklärt jedoch nicht, warum dies erforderlich ist.
Mark Amery
aber wie es iframes verhindern wird
Ravinder Payal
Skript-Tags sind niemals von derselben Ursprungsrichtlinie ausgenommen. Könnten Sie das für mich klären?
Suraj Jain
82

Hinweis : Ab 2019 sind viele der alten Sicherheitslücken, die zu den in dieser Frage diskutierten vorbeugenden Maßnahmen führen, in modernen Browsern kein Problem mehr. Ich werde die Antwort unten als historische Kuriosität belassen, aber wirklich hat sich das ganze Thema seit 2010 (!!) radikal verändert, als dies gefragt wurde.


Es verhindert, dass es als Ziel eines einfachen <script>Tags verwendet wird. (Nun, es verhindert es nicht, aber es macht es unangenehm.) Auf diese Weise können Bösewichte dieses Skript-Tag nicht einfach in ihre eigene Site einfügen und sich auf eine aktive Sitzung verlassen, um das Abrufen Ihrer Inhalte zu ermöglichen.

Bearbeiten - Notieren Sie den Kommentar (und andere Antworten). Das Problem hat mit untergrabenen eingebauten Einrichtungen zu tun, insbesondere den Konstruktoren Objectund Array. Diese können so geändert werden, dass ansonsten harmloses JSON beim Analysieren Angreifercode auslösen kann.

Spitze
quelle
17
Dies ist nur eine halbe Antwort. Ohne den Trick, die Konstruktoren Objectund zu überschreiben Array, wäre es unter allen Umständen völlig harmlos, eine gültige JSON-Antwort so auszuführen, als wäre es JavaScript. Ja, das while(1);verhindert , dass die Antwort als JavaScript ausgeführt wird, wenn sie von einem <script>Tag als Ziel ausgewählt wird. Ihre Antwort erklärt jedoch nicht, warum dies erforderlich ist.
Mark Amery
11

Da das <script>Tag von der Same Origin-Richtlinie ausgenommen ist, die in der Webwelt eine Sicherheitsbedingung darstellt, wird while(1)durch das Hinzufügen zur JSON-Antwort ein Missbrauch im <script>Tag verhindert.

Krishna Ganeriwal
quelle