Provoquer un crash du navigateur avec fuzzing comportemental

image

Dans cet article, je vais vous expliquer comment j'ai utilisé le fuzzing pour trouver plusieurs plantages dans Firefox. En règle générale, le fuzzing a pour but de trouver une défaillance qui indique une corruption de la mémoire, mais mon objectif est différent: je veux détecter une réaction de navigateur inattendue. Il peut s'agir de caractères qui ouvrent ou ferment une balise inhabituelle ou, éventuellement, de caractères ignorés par l'analyseur JavaScript. Une telle réaction inattendue peut souvent être utilisée pour mener des attaques XSS, contourner les filtres de sécurité et éviter le sandbox JavaScript.

La première erreur dont je veux parler est de savoir comment fermer le commentaire HTML d'une manière différente. Si vous lisez la spécification HTML, vous savez qu'un commentaire peut être fermé avec -> ou -!>. Mais comment faire autrement? Grande question pour commencer le fuzzing! Il vous suffit de générer le code qui donnera la réponse.

En 2008, lorsque j'ai assemblé Shazzer pour un comportement de navigateur fuzz, j'étais limité à environ 10 000 directions par page. Aujourd'hui, en 2019, tout fonctionne plus rapidement, nous pouvons donc jouer beaucoup plus souvent. De plus, l'utilisation du DOM accélère le fuzzing car vous n'avez plus besoin d'ajouter chaque direction au document actuel. Il convient de noter qu'il s'agit d'une approche peu fiable, car vous pouvez obtenir des résultats différents. En effet, j'ai trouvé des cas où le DOM autorise des valeurs nulles dans des arguments d'attribut tels que href, mais pas l'analyseur HTML. Ce sont toujours des échecs non critiques, mais vous ne pouvez pas toujours faire confiance aux résultats afin d'avoir une image complète de ce que fera l'analyseur HTML. Cependant, dans la plupart des cas, cela fonctionne et c'est beaucoup plus rapide que la sortie HTML du côté serveur.

La première étape a déjà été franchie - nous avons une question: "Quels caractères peuvent fermer le commentaire HTML?". Pour y répondre, nous devons utiliser des caractères existants qui fermeront le commentaire HTML et des caractères fuzz que nous ne connaissons pas. L'étape suivante consiste à utiliser un logiciel de fuzzing approprié. Dans mon cas, j'utilise mon outil Hackvertor , mais en utilisant le serveur Web local, je peux obtenir les mêmes résultats. L'idée de cet outil est de mettre l'entrée dans le champ de saisie, de convertir un peu les balises et de faire quelque chose avec la sortie. Comme nous n'avons rien à convertir, nous pouvons mettre notre code directement dans le champ de sortie. Par conséquent, cliquez sur la zone de sortie de texte et créez un tableau pour stocker les caractères flous et un élément div pour tester le HTML:

log = []; div=document.createElement('div'); 

Ensuite, nous devons extraire plus de 1 000 000 de caractères Unicode ou, plus précisément, 0x10ffff. Une simple boucle for est tout ce dont nous avons besoin:

 for(i=0;i<=0x10ffff;i++){ 

Ensuite, nous réutilisons l'élément div que nous avons créé pour chaque personnage. Dans ce cas, je teste la position après! Pour que le caractère soit saisi après! .. Ensuite j'utilise l'élément img pour voir si le fuzzing a réussi. Si cet élément existe, alors le commentaire HTML a été fermé et nous avons quelques caractères intéressants!

 div.innerHTML = '<!-- --!'+String.fromCodePoint(i)+'><img>-->'; 

Enfin, avec querySelector, nous vérifions si img existe et ajoutons des caractères aux journaux. Ensuite, je ferme l'instruction if et la boucle for. Enfin, j'entre les résultats dans le champ de saisie à gauche:

 if(div.querySelector('img')){ log.push(i); } } input.value=log 

Voici la version complète du code. Vous devez ouvrir l'URL dans Firefox, puis mettre les caractères d'entrée dans le champ de sortie et cliquer sur le bouton "Exécuter JS" pour flou les caractères. Après avoir terminé le fuzzing, vous devriez voir les nombres dans le champ de saisie, ils correspondent aux codes de caractères qui ont réussi. Au moment de l'écriture, Firefox (version 67) autorise toujours les caractères de nouvelle ligne - \ n et \ r - après!, Pour fermer le commentaire. J'ai été informé que cela a été corrigé dans les futures versions de Firefox. Donc, la dernière étape du fuzzing est de construire votre charge utile, c'est assez simple. Vous devez remplacer le code de caractère par le caractère et ajouter la charge utile XSS:

 <!-- --! ><img src=1 onerror=alert(1)> --> 

Vous pouvez à nouveau utiliser Hackvertor pour tester son fonctionnement en collant ce qui précède dans le champ de sortie, puis en cliquant sur «Test HTML». Une fenêtre d'avertissement devrait apparaître car Firefox (version 67) résout la nouvelle ligne dans le cadre du commentaire final.

Cela nous a donc permis de trouver une erreur non critique dans l'analyseur HTML Firefox. Trouvons-en un autre! Nous avons besoin d'une nouvelle question: "Quels caractères peuvent ouvrir un commentaire HTML?". Au lieu d'aller au-delà du commentaire HTML existant, nous allons maintenant utiliser le commentaire HTML pour aller au-delà de l'attribut HTML existant. Comme je suis sûr, vous savez tous que vous pouvez ouvrir un commentaire HTML avec <! -. Ça va? Nous utiliserons à nouveau le même code, mais cette fois changez le but de innerHTML pour vérifier si le commentaire est ouvert:



Ainsi, le symbole que nous flouons sera après le premier tiret. Si le caractère crée avec succès un commentaire HTML d'ouverture, il commentera l'élément div et quittera ainsi l'attribut title. Cette fois, lorsque nous exécutons «Exécuter JS», nous obtenons deux résultats dans Firefox (version 67): «0.45». Le code 45 est attendu car il s'agit d'un trait d'union, mais 0 est un caractère NULL! Cela signifie que Firefox interprète la séquence <! - NULL- comme un commentaire ouvert. Une sorte de jeu! (Je pense que les fournisseurs de navigateurs ont besoin de plus de fuzzing comportemental =)). Pour terminer ce cas de test, nous devons maintenant créer notre direction. Faisons de même: encore une fois, remplacez la fonction String.fromCodePoint par le symbole NULL et XSS par la direction:

 document.body.innerHTML = '<!-\x00- ><div title="--><img src=1 onerror=alert(1)>"></div>'; 

Passons à JavaScript au lieu de HTML. J'ai testé tous les navigateurs et je suis désolé Mozilla, mais Firefox refait une sorte de jeu. J'ai été inspiré par le fait que le fuzzing du tweet jinmo123 utilise de nouvelles fonctionnalités ES6 intéressantes pour appeler des fonctions sans parenthèses. La question que j'ai trouvée pour le fuzzing était: "quels caractères sont autorisés après les opérateurs in ou instanceof?" Ensuite, nous créons à nouveau le code dans Hackvertor, il suit un modèle similaire, mais cette fois n'utilise pas le DOM. Créez d'abord un tableau et une boucle for:

 log = []; for(i=0;i<=0x10ffff;i++){ 

Ensuite, nous utiliserons eval au lieu de innerHTML pour flou nos valeurs. Nous devons d'abord utiliser un bloc try catch pour détecter les exceptions causées par des caractères non valides.

 try{ eval("/a/"+String.fromCodePoint(i)+"instanceof function(){}"); 

La fonction eval est utilisée pour voir si notre JavaScript est valide. Si c'est le cas, il passera à la ligne suivante; sinon, il lèvera une exception qui sera remarquée, puis passera au caractère suivant. La ligne suivante enregistre simplement le caractère, puis ferme le bloc try catch et la boucle for. La fonction affiche ensuite les résultats dans le champ de saisie.

 log.push(i); }catch(e){} } input.value=log 

Si vous exécutez ce code en utilisant "Exécuter JS", vous obtiendrez un tas de résultats! Firefox ignore de nombreux caractères. Si vous essayez le code sur Chrome, vous obtiendrez des résultats plus raisonnables. Trouvez le code de caractère dans le champ de saisie que vous souhaitez utiliser, dans mon cas c'était «1114110» ou «0x10fffe» en hexadécimal. Nous allons maintenant créer notre vecteur JavaScript:

 eval("1337"+String.fromCodePoint(1114110)+"in"+String.fromCodePoint(1114110)+"alert(1337)"); 

Vous pouvez également l'imaginer dans un script SVG:



Les dernières configurations à double processeur de serveurs dédiés avec les processeurs évolutifs Intel 2019 sont disponibles sur DEDIC.SH :
  • 2x Xeon Silver 4214 - un total de 24 cœurs
  • 2x Xeon Gold 5218 - un total de 32 cœurs
  • 2x Xeon Gold 6240 - configuration avec 36 cœurs.

Le coût d'un serveur avec deux Xeon Silver 4214 - à partir de 15210 roubles / mois
Nous sommes également prêts à collecter toute configuration pour vous - écrivez-nous !

Si de grandes puissances d'un serveur dédié ne sont pas nécessaires - VDS à partir de 150 roubles / mois est ce dont vous avez besoin!

Source: https://habr.com/ru/post/fr455602/


All Articles