Duplicate possible:
Pourquoi les gens mettent-ils du code du type “jeter 1; <ne soyez pas diabolique>” et “pour (;;);” devant les réponses json?
J'ai trouvé ce type de syntaxe utilisé sur Facebook pour les appels Ajax. Je suis confus sur la partie for (;;);
au début de la réponse. A quoi cela sert?
C'est l'appel et la réponse:
GET http://0.131.channel.facebook.com/x/1476579705/51033089/false/p_1524926084=0
Réponse:
for (;;);{"t":"continue"}
Je suis un peu en retard et T.J. a essentiellement résolu le mystère, mais je pensais partager un excellent article sur ce sujet particulier, qui contient de bons exemples et fournit un aperçu plus approfondi de ce mécanisme.
Ces boucles infinies sont une contre-mesure contre le "détournement de Javascript", un type d'attaque qui a attiré l'attention du public avec une attaque sur Gmail publiée par Jeremiah Grossman .
L'idée est aussi simple que belle: de nombreux utilisateurs ont tendance à se connecter en permanence à Gmail ou à Facebook. Donc, ce que vous faites est de configurer un site et dans le code Javascript de votre site malveillant, vous substituez le constructeur d'objet ou de tableau:
function Object() {
//Make an Ajax request to your malicious site exposing the object data
}
alors vous incluez un <script>
tag dans ce site tel que
<script src="http://www.example.com/object.json"></script>
Et enfin, vous pouvez tout savoir sur les objets JSON dans les journaux de votre serveur malveillant.
Comme promis, le lien vers le papier .
Je soupçonne que la raison principale en est le contrôle. Il vous oblige à récupérer les données via Ajax, et non via JSON-P ou similaire (qui utilise les balises script
et échouera donc parce que cette boucle for
est infinie) et garantit ainsi que la même règle d'origine entre en jeu. Cela leur permet de contrôler quels documents peuvent émettre des appels à l'API - en particulier, seuls les documents contenant même origine que cet appel d’API, ou ceux auxquels Facebook accorde spécifiquement l’accès via CORS (sur les navigateurs prenant en charge CORS). Vous devez donc demander les données via un mécanisme dans lequel le navigateur applique la SOP, vous devez connaître cette préface et la supprimer avant de désérialiser les données.
Donc oui, il s'agit de contrôler l'accès (utile) à ces données.
Facebook emploie une multitude de développeurs travaillant en interne sur de nombreux projets et il est très courant que quelqu'un commette une petite erreur. que ce soit quelque chose d'aussi simple et sérieux que de ne pas échapper des données insérées dans un modèle HTML ou SQL ou quelque chose d'aussi complexe et subtil que d'utiliser eval
(parfois inefficace et sans doute insécure) ou JSON.parse
(a conforme à la norme mais non implémentée universellement) au lieu d’un décodeur JSON "de qualité", il est important de trouver des moyens d’appliquer facilement les meilleures pratiques à cette population de développeurs.
Pour faire face à ce défi, Facebook a récemment adopté des projets internes conçus pour appliquer ces meilleures pratiques avec élégance. Pour être honnête, la seule explication qui ait du sens pour ce cas particulier est justement cela: quelqu'un a décidé en interne que tous les l'analyse doit passer par une seule implémentation dans leur bibliothèque principale, et le meilleur moyen de le faire respecter est que chaque réponse de l'API obtienne for(;;);
automatiquement ajoutée au premier plan.
En faisant cela, un développeur ne peut pas être "paresseux": ils remarqueront immédiatement s'ils utilisent eval()
, se demandent ce qui se passe, puis réalisent leur erreur et utilisent l'approbation API JSON.
Les autres réponses fournies semblent toutes appartenir à l'une des deux catégories suivantes:
Les utilisateurs de la première catégorie s’appuient sur l’idée selon laquelle un attaquant peut en quelque sorte envoyer une requête "utilisant JSONP" à une API qui ne la prend pas en charge. JSONP est un protocole qui doit être pris en charge à la fois sur le serveur et sur le client: il nécessite que le serveur retourne quelque chose qui s'apparente à myFunction({"t":"continue"})
, de sorte que le résultat soit transmis à une fonction locale. Vous ne pouvez pas simplement "utiliser JSONP" par accident.
Ceux de la deuxième catégorie citent une vulnérabilité très réelle qui permet une falsification de requête intersite via des balises vers des API qui ne le font pas utilisent JSONP (comme celui-ci), permettant à un " JSON détournant ". Cela se fait en changeant le constructeur Array/Object, ce qui permet d'accéder aux informations renvoyées par le serveur sans fonction d'encapsulation.
Cependant, cela n’est tout simplement pas possible dans ce cas: la raison pour laquelle cela fonctionne est qu’un tableau vide (un résultat possible de nombreuses API JSON, comme le célèbre exemple Gmail) est une déclaration d’expression valide, ce qui n’est pas le cas d’un objet nu.
En fait, la syntaxe des objets définis par JSON (qui inclut des guillemets autour des noms de champs, comme indiqué dans cet exemple) est en conflit avec la syntaxe des blocs et ne peut donc pas être utilisée au niveau supérieur d'un script.
js> {"t":"continue"}
typein:2: SyntaxError: invalid label:
typein:2: {"t":"continue"}
typein:2: ....^
Pour que cet exemple soit exploitable au moyen du remappage du constructeur Object (), il faudrait que l’API ait plutôt renvoyé l’objet à l’intérieur d’un ensemble de parenthèses, ce qui le rend valide JavaScript (mais non valide JSON).
js> ({"t":"continue"})
[object Object]
Maintenant, pourrait peut-être que cette astuce de préfixe for(;;);
n'apparaît que "par accident" dans cet exemple et est en fait renvoyée par d'autres API Facebook internes qui renvoient des tableaux; mais dans ce cas, cela devrait vraiment être noté, car ce serait alors la "vraie" cause de la raison pour laquelle for(;;);
apparaît dans cet extrait de code spécifique.
Eh bien, la for(;;);
est une boucle infinie (vous pouvez utiliser la console JavaScript de Chrome pour exécuter ce code dans un onglet, si vous le souhaitez, puis observez l'utilisation du processeur dans le gestionnaire de tâches jusqu'à ce que le navigateur supprime l'onglet).
Donc, je suppose que cela est peut-être mis là pour frustrer quiconque tente d'analyser la réponse en utilisant eval
ou toute autre technique qui exécute les données renvoyées.
Pour expliquer davantage, il était assez courant d'analyser un peu de données au format JSON à l'aide de la fonction JavaScript eval()
, en procédant comme suit:
var parsedJson = eval('(' + jsonString + ')')
;
... ceci est considéré comme dangereux, cependant, comme si, pour une raison quelconque, vos données au format JSON contenaient du code JavaScript exécutable au lieu de (ou en plus des) données au format JSON, ce code serait exécuté par la eval()
. Cela signifie que si vous parlez à un serveur non approuvé ou si quelqu'un compromet un serveur de confiance, il peut alors exécuter du code arbitraire sur votre page.
Pour cette raison, l'utilisation d'éléments tels que eval()
pour analyser des données au format JSON est généralement mal vue, et l'instruction for(;;);
dans le JSON de Facebook empêchera les utilisateurs d'analyser les données de cette façon. Toute personne qui essaye aura une boucle infinie. En gros, c'est comme si Facebook essayait de faire en sorte que les gens travaillent avec ses API de manière à ne pas les rendre vulnérables aux futurs exploits qui tentent de détourner l'API de Facebook pour qu'elle soit utilisée comme vecteur.
Cela ressemble à un hack pour empêcher une attaque CSRF . Il existe des méthodes spécifiques au navigateur pour s’intégrer à la création d’objets. Ainsi, un site Web malveillant peut le faire en premier, puis avoir les éléments suivants:
<script src="http://0.131.channel.facebook.com/x/1476579705/51033089/false/p_1524926084=0" />
S'il n'y avait pas de boucle infinie avant le JSON, un objet serait créé, car le JSON peut être eval()
ed comme javascript. , et les crochets le détectent et reniflent les membres de l’objet.
Maintenant, si vous visitez ce site à partir d’un navigateur, alors que vous êtes connecté à Facebook, il peut accéder à vos données comme si c’était vous, puis les renvoyer à son propre serveur via, par exemple, un AJAX ou post javascript.