Apprendre le XSS avec le jeu XSS de Google
Instruction étape par étape sur la façon de résoudre le jeu XSS de Google
XSS aka Cross Site Scripting est l’une des dangereuses vulnérabilités côté client et l’une des méthodes de chasse aux bugs les plus appréciées.
Google XSS Game est une plateforme de formation fournie par google pour pratiquer le XSS. Il se compose de 6 niveaux et dans chaque niveau, vous devez exécuter une alerte JavaScript afin de passer au niveau suivant. Dans chaque niveau, on vous fournira différents problèmes et vous devrez exécuter l’alerte en utilisant différentes techniques dans chaque niveau. Cela vous aidera à comprendre les différentes méthodes qui peuvent être utilisées pour exécuter XSS dans une page Web.
Donc, commençons.
Naviguez vers https://xss-game.appspot.com. C’est là que le jeu Google XSS est disponible.
Vous verrez une page comme celle-ci
Cliquez sur le bouton Let me at ’em ! pour entrer dans le jeu.
Première tâche : Bonjour monde du XSS
Vous devez injecter la charge utile xss dans le navigateur virtuel. Vous pouvez visualiser le code source en cliquant sur le lien « toggle ». Si vous ne parvenez pas à injecter, vous pouvez obtenir les indices en cliquant sur le lien « show ».
En vérifiant le code source, il s’agit d’un script python et les 2 parties intéressantes dans la fonctiondef get(self)
sont
et
query = self.request.get('query', '')
message = "Sorry, no results were found for <b>" + query + "</b>."
message += " <a href='?'>Try again</a>."
La première partie désactivera le vérificateur XSS de chrome et nous permettra d’injecter la charge utile XSS dans le navigateur.
La deuxième partie montre que la valeur du paramètre url query
est directement ajoutée au corps. C’est là que nous devons exploiter.
C’est un simple et vous pouvez essayer d’entrer n’importe lequel des éléments suivants (et même plus sont là) dans la boîte de recherche et de le rechercher
<a href="javascript:alert()">Link</a>
<img src=X onerror="alert()">
<script>alert()</script>
Et ainsi de suite. Si vous avez utilisé le premier, vous devez cliquer sur le lien afin d’exécuter l’alerte.
Génial !!!! Vous avez terminé avec succès le niveau 1. Maintenant vous verrez un bouton pour passer au niveau suivant.
Deuxième tâche : La persistance est la clé
Dans cette tâche, vous devez exécuter l’alerte en ajoutant un post. Dans ce jeu, il s’agit d’un DOM XSS, mais lors du test sur des applications réelles de chat/commentaires, il s’agira d’un stored XSS.
Ok jetons un coup d’œil à la source et au message précédent également.
En inspectant la source, vous pouvez voir que le message par défaut utilise différents types de balises html pour le styliser. C’est notre clé.
Vérifiez la source pour le confirmer. Voici comment notre message est rendu
Vous pouvez voir que le message ne passe par aucun filtre. Nous pouvons donc utiliser n’importe quelle méthode mentionnée ci-dessus.
<a href="javascript:alert()">Link</a>
<img src=X onerror="alert()">
Et ainsi de suite.
Congrats. Vous avez terminé le niveau 2. Maintenant, passez au niveau suivant.
Tâche 3 : Ce sentiment d’enfoncement
Nous avons un espace pour entrer la durée du minuteur. C’est là que nous allons exploiter.
Vérifions le code source.
Dans timer.html, nous pouvons voir cette ligne
<img src="https://medium.com/static/loading.gif" onload="startTimer('{{ timer }}');" />
Nous devons exploiter dans l’expression {{ timer }}
Mais elle est placée à l’intérieur d’une fonction startTimer('');
qui est un gestionnaire de l’événement onload
. Le point principal à noter est que l’attribut de gestionnaire d’événement en HTML accepte plusieurs fonctions de rappel.
Nous devons donc fermer la fonction et y exécuter notre alerte. Notez que, la valeur n’est pas passée par une fonction parseInt
au lieu que les données brutes sont utilisées. Nous pouvons donc fermer la fonction en ajoutant un ');
et ensuite injecter notre alert
. Puisqu’il est utilisé comme inline, nous ne pouvons pas injecter alert();
là car cela cassera les choses. L’instruction deviendra onload="startTimer('3'); alert();')"
et cela ne fonctionnera pas.
Donc nous devons ajouter un motif qui garde le motif intact.
Ajouter alert('
et c’est suffisant.
Donc notre charge utile sera
3');alert('
Cliquer sur le bouton de démarrage du minuteur exécutera l’alerte et nous avons terminé ce niveau.
Avancer à la tâche suivante.
Tâche 5 : Rupture du protocole
Dans la page d’accueil, nous n’avons pas de moyen d’injecter quoi que ce soit. Tout ce que nous avons, c’est un lien. Alors cliquons dessus.
Ici, nous pouvons voir 2 endroits pour injecter notre charge utile. un sur l’url elle-même et un autre sur la boîte de saisie. La boîte de saisie est un endroit pour entrer l’email et espérer qu’il ne sera pas reflété ailleurs. Donc allons au premier endroit. Sur l’url.
Inspectez le code source de la pag actuelle, c’est-à-dire signup.html et nous pouvons voir la ligne
<a href="{{ next }}">Next >></a>
Grand endroit pour injecter une charge utile. Notre charge utile sera définie comme la valeur de l’attribut href
dans une balise a
. Si nous sommes capables d’ajouter javascript:alert()
nous pouvons exécuter notre payload. Maintenant, voyons quelle est la valeur de next
. Nous ne pouvons pas en trouver dans la page. Où devons-nous la chercher ?
Le code Python à la rescousse. Vérifiez level.py et nous verrons
if "signup" in self.request.path:
self.render_template('signup.html',
{'next': self.request.get('next')})
Donc la valeur de next
dans l’url sera utilisée.
Changez la valeur de next
dans l’url de confirm
à javascript:alert()
et l’url final ressemblera à
Now clicking on Next >> in the page will trigger our payload.
We now completed level 5. And 1 level remains.
Task 6 : Follow the 🐇
There is a path to a js file in the url.
Let’s inspect the source code. In page index.html, you can see a function includeGadget
et à l’intérieur du corps de la fonction, vous pouvez voir le code suivant.
var scriptEl = document.createElement('script');
So nous pouvons charger un fichier js externe mais pas à partir d’une url http
ou https
.
Dans ce cas, essayons les urls data
.
Les urls de données sont sous la forme data:{type},content
Alors changez la valeur après #
en
data:application/javascript,alert()
ou en
data:text/plain,alert()
et nous pouvons exécuter le alert
.
Voici une vidéo de la résolution du Jeu.
.