Pourquoi Google ajoute-t-il while(1);
à ses réponses JSON (privées)?
Par exemple, voici une réponse lors de l'activation et de la désactivation d'un calendrier dans Google Calendar :
while(1);[['u',[['smsSentFlag','false'],['hideInvitations','false'],
['remindOnRespondedEventsOnly','true'],
['hideInvitations_remindOnRespondedEventsOnly','false_true'],
['Calendar ID stripped for privacy','false'],['smsVerifiedFlag','true']]]]
J'imagine que c'est pour empêcher les gens de faire une eval()
dessus, mais tout ce que vous auriez à faire est de remplacer la while
et vous seriez alors réglé. Je suppose que la prévention eval consiste à s'assurer que les personnes écrivent du code d'analyse syntaxique JSON sécurisé.
J'ai déjà vu cela dans quelques autres pays, mais beaucoup plus souvent avec Google (courrier, agenda, contacts, etc.). Étrangement, Google Docs commence par &&&START&&&
à la place, et Google Contacts semble commencer par while(1); &&&START&&&
.
Que se passe t-il ici?
Cela empêche détournement de JSON , un problème de sécurité majeur pour JSON qui est officiellement corrigé dans tous les principaux navigateurs depuis 2011 avec ECMAScript 5.
Exemple élaboré: disons que Google a une URL du type mail.google.com/json?action=inbox
qui renvoie les 50 premiers messages de votre boîte de réception au format JSON. Les sites Web malveillants situés sur d'autres domaines ne peuvent pas demander AJAX d'obtenir ces données en raison de la règle de même origine, mais ils peuvent inclure l'URL via une balise <script>
. L'URL est visitée avec vos cookies et par en remplaçant le constructeur du tableau global ou les méthodes d'accès ils peuvent avoir une méthode appelée à tout moment un attribut object (array ou hash) est défini, leur permettant de lire le contenu JSON.
La while(1);
ou &&&BLAH&&&
empêche ceci: une demande AJAX sur mail.google.com
aura un accès complet au contenu du texte et pourra le supprimer. Mais une insertion de balise <script>
exécute aveuglément le code JavaScript sans aucun traitement, ce qui entraîne une boucle infinie ou une erreur de syntaxe.
Cela ne règle pas le problème de falsification de requête intersite .
Il empêche la divulgation de la réponse via le détournement JSON.
En théorie, le contenu des réponses HTTP est protégé par la règle de la même origine: les pages d'un domaine ne peuvent obtenir aucune information provenant de pages de l'autre domaine (sauf autorisation explicite).
Un attaquant peut demander des pages sur d'autres domaines en votre nom, par exemple. en utilisant une balise <script src=...>
ou <img>
, mais elle ne peut obtenir aucune information sur le résultat (en-têtes, contenu).
Ainsi, si vous visitez la page d'un attaquant, il ne pourra pas lire votre courrier électronique depuis gmail.com.
Sauf que lorsque vous utilisez une balise de script pour demander du contenu JSON, celui-ci est exécuté en tant que Javascript dans l'environnement contrôlé par l'attaquant. Si l'attaquant peut remplacer le constructeur Array ou Object ou une autre méthode utilisée lors de la construction de l'objet, tout élément du code JSON transiterait par le code de l'attaquant et serait divulgué.
Notez que cela se produit au moment où le JSON est exécuté en Javascript, pas au moment de son analyse.
Il existe plusieurs contre-mesures:
En plaçant une instruction while(1);
avant les données JSON, Google s'assure que les données JSON ne sont jamais exécutées en tant que Javascript.
Seule une page légitime peut obtenir le contenu entier, effacer la while(1);
et analyser le reste en tant que JSON.
Des choses comme for(;;);
ont par exemple été vues sur Facebook, avec les mêmes résultats.
De même, l'ajout de jetons non valides avant le JSON, comme &&&START&&&
, permet de s'assurer qu'il n'est jamais exécuté.
Ceci est OWASP
recommandé pour se protéger du piratage JSON et est le moins intrusif.
À l'instar des contre-mesures précédentes, il s'assure que le JSON n'est jamais exécuté en Javascript.
Un objet JSON valide, lorsqu'il n'est entouré par rien, n'est pas valide en Javascript:
eval('{"foo":"bar"}')
// SyntaxError: Unexpected token :
Ceci est cependant valide JSON:
JSON.parse('{"foo":"bar"}')
// Object {foo: "bar"}
Ainsi, vous assurer de toujours renvoyer un objet au plus haut niveau de la réponse garantit que le JSON n'est pas valide comme Javascript, tout en restant valide.
Comme indiqué par @hvd dans les commentaires, l'objet vide {}
est valide Javascript, et savoir que l'objet est vide peut être en soi une information précieuse.
La méthode OWASP est moins intrusive, car elle ne nécessite aucune modification de la bibliothèque client et transfère un code JSON valide. Il n’est toutefois pas certain que des bogues de navigateur antérieurs ou futurs puissent résoudre ce problème. Comme l'a noté @oriadam, il n'est pas clair si les données risquent d'être divulguées dans une erreur d'analyse via une gestion d'erreur ou non (par exemple, window.onerror).
La méthode de Google nécessite une bibliothèque cliente afin de prendre en charge la dé-sérialisation automatique et peut être considérée comme plus sûre vis-à-vis des bogues de navigateur.
Les deux méthodes nécessitent des modifications côté serveur afin d'éviter aux développeurs d'envoyer accidentellement des fichiers JSON vulnérables.
Cela permet de s’assurer que certains autres sites ne peuvent pas faire de mauvais tours pour voler vos données. Par exemple, en remplaçant le constructeur de tablea , puis en incluant cette URL JSON via une balise <script>
, un site tiers malveillant pourrait voler les données de la réponse JSON. En mettant un while(1);
au début, le script se bloque à la place.
En revanche, une requête de même site utilisant XHR et un analyseur JSON séparé peuvent facilement ignorer le préfixe while(1);
.
Cela empêcherait une tierce partie d'insérer la réponse JSON dans un document HTML portant la balise <script>
. Rappelez-vous que la balise <script>
est exempte de la règle politique de même origine .
Note: à partir de 2019, bon nombre des anciennes vulnérabilités ayant conduit aux mesures préventives évoquées dans cette question ne sont plus un problème pour les navigateurs modernes. Je laisserai la réponse ci-dessous à titre de curiosité historique, mais le sujet dans son ensemble a radicalement changé depuis 2010 (!!), date à laquelle cette question a été posée.
Cela l'empêche d'être utilisé comme cible d'une simple balise <script>
. (Eh bien, cela ne l’empêche pas, mais cela le rend désagréable.) De cette façon, les méchants ne peuvent pas simplement placer cette balise de script sur leur propre site et s’appuyer sur une session active pour pouvoir récupérer votre contenu.
edit - notez le commentaire (et les autres réponses). Le problème concerne les installations intégrées subverties, en particulier les constructeurs Object
et Array
. Celles-ci peuvent être modifiées de telle sorte que du JSON inoffensif, une fois analysé, puisse déclencher le code de l'attaquant.
Étant donné que la balise <script>
est exemptée de la politique de même origine, qui est une nécessité de sécurité dans le monde Web, while(1)
lorsqu'elle est ajoutée à la réponse JSON empêche son utilisation abusive dans la balise <script>
.