Introduction
Le Cross-Site Scripting (XSS) réfléchi est une vulnérabilité web courante qui survient lorsqu'une application reçoit des données dans une requête HTTP et les inclut dans la réponse HTTP immédiate de manière non sécurisée. Étant donné que le script malveillant injecté est « réfléchi » par le serveur web, il s'exécute dans le navigateur de la victime, permettant aux attaquants de voler des cookies de session, d'effectuer des actions au nom de l'utilisateur ou de défigurer le site web.
L'idée fondamentale est que le XSS est un bug d'exécution de code côté navigateur. Le serveur peut refléter la charge utile, mais c'est dans le navigateur que le script s'exécute réellement et que la frontière de confiance est rompue.
Dans ce laboratoire, vous interagirez avec une application web vulnérable hébergée localement. Vous apprendrez l'approche systématique pour trouver et exploiter un XSS réfléchi : localiser où votre saisie est reflétée, tester la manière dont l'application gère les caractères spéciaux, sortir de la structure HTML existante et, enfin, exécuter une charge utile JavaScript malveillante.
Localiser les points de réflexion
Dans cette étape, vous apprendrez à identifier les points de réflexion dans une application web. Un point de réflexion est un emplacement dans la réponse HTTP de l'application où la saisie que vous avez fournie dans la requête HTTP est affichée (ou « réfléchie ») vers vous.
Nous avons démarré une application web vulnérable sur votre machine locale, accessible sur le port 8080. Cette application dispose d'une fonctionnalité de recherche qui prend un paramètre de requête nommé q.
Pour trouver un point de réflexion, vous devez envoyer une chaîne unique et facilement identifiable à l'application et vérifier si elle apparaît dans le code source de la réponse. Nous utiliserons l'outil en ligne de commande curl pour envoyer une requête HTTP GET à l'application.
La réflexion est nécessaire mais pas suffisante. Votre saisie doit revenir dans un contexte où l'analyseur du navigateur peut la transformer en code exécutable.
Exécutez la commande suivante dans votre terminal pour envoyer une chaîne de test REFLECTION_TEST au point de terminaison de recherche :
curl -s "http://localhost:8080/search?q=REFLECTION_TEST"
Observez attentivement la sortie HTML affichée dans votre terminal. Vous devriez voir votre saisie REFLECTION_TEST intégrée directement dans la structure HTML.
<!DOCTYPE html>
<html>
<head><title>Search Results</title></head>
<body>
<h2>Search Results</h2>
<form action="/search" method="GET">
<input type="text" name="q" value="REFLECTION_TEST">
<button type="submit">Search Again</button>
</form>
</body>
</html>
Notez que votre saisie est placée à l'intérieur de l'attribut value d'une balise <input>. Cela confirme que l'application récupère notre saisie depuis l'URL et la reflète directement dans la réponse HTML. C'est la première condition requise pour une vulnérabilité XSS réfléchie.
Tester le filtrage des caractères (< > ")
Dans cette étape, vous testerez si l'application assainit ou filtre les caractères HTML spéciaux.
L'encodage sensible au contexte est la véritable défense ici. Les caractères dangereux diffèrent selon que la saisie se trouve dans le corps du texte d'un élément, un attribut HTML, du JavaScript ou une URL.
Trouver un point de réflexion ne suffit pas à confirmer une vulnérabilité XSS. Les frameworks web modernes encodent souvent automatiquement les caractères spéciaux. Par exemple, un signe inférieur < peut être converti en <. Si l'application encode ces caractères, le navigateur les traitera comme du texte sûr plutôt que comme du code exécutable, empêchant ainsi le XSS.
Pour injecter du HTML ou du JavaScript malveillant, nous avons généralement besoin de caractères comme le signe inférieur < (pour démarrer une balise), le signe supérieur > (pour fermer une balise) et les guillemets doubles " (pour manipuler les attributs).
Envoyons une nouvelle charge utile contenant ces caractères spéciaux pour voir comment l'application les gère. Nous utiliserons des guillemets simples autour de l'URL dans notre commande curl pour empêcher le shell Linux d'interpréter les caractères spéciaux.
Exécutez la commande suivante pour tester le filtrage des caractères :
curl -s 'http://localhost:8080/search?q=FILTER_TEST<>"'
Examinez la sortie renvoyée par le serveur :
<!DOCTYPE html>
<html>
<head><title>Search Results</title></head>
<body>
<h2>Search Results</h2>
<form action="/search" method="GET">
<input type="text" name="q" value="FILTER_TEST<>"">
<button type="submit">Search Again</button>
</form>
</body>
</html>
Observez l'attribut value dans la balise <input>. Les caractères <>" sont réfléchis exactement tels que nous les avons envoyés, sans aucun encodage HTML (comme < ou "). Cette absence d'assainissement confirme que l'application est très probablement vulnérable au Cross-Site Scripting.
Sortir des contextes HTML
Dans cette étape, vous apprendrez à sortir du contexte HTML actuel pour préparer l'injection de la charge utile.
C'est le cœur du travail pratique sur le XSS : comprendre le contexte de l'analyseur dans lequel vous commencez, puis utiliser la syntaxe pour en sortir en toute sécurité vers un contexte plus dangereux.
Le contexte est crucial en XSS. Dans notre application vulnérable, le point de réflexion se trouve à l'intérieur d'un attribut HTML : value="[VOTRE_SAISIE]". Si nous injectons simplement une balise <script> immédiatement, elle fera partie de la valeur textuelle du champ de saisie, au lieu d'être exécutée par le navigateur.
Pour forcer le navigateur à exécuter notre code, nous devons d'abord « sortir » de l'attribut value et fermer la balise <input>.
Puisque l'attribut est entouré de guillemets doubles, nous pouvons injecter un guillemet double " pour fermer l'attribut value prématurément. Ensuite, nous pouvons injecter un signe supérieur > pour fermer la balise <input> elle-même.
Testons cette technique d'évasion. Envoyez la charge utile suivante à l'application :
curl -s 'http://localhost:8080/search?q=BREAKOUT">'
Examinez attentivement la sortie HTML :
<!DOCTYPE html>
<html>
<head><title>Search Results</title></head>
<body>
<h2>Search Results</h2>
<form action="/search" method="GET">
<input type="text" name="q" value="BREAKOUT">">
<button type="submit">Search Again</button>
</form>
</body>
</html>
Regardez ce qui est arrivé à la balise <input>. Le HTML se lit maintenant value="BREAKOUT">">.
Notre " injecté a réussi à fermer l'attribut value, et notre > injecté a fermé la balise <input>. Le "> restant à la fin est le guillemet fermant et le crochet d'origine provenant du modèle de l'application, qui sont maintenant laissés en suspens comme du texte inoffensif sur la page.
Vous avez réussi à sortir du contexte de l'attribut HTML. L'espace suivant immédiatement votre charge utile est maintenant traité comme du contenu HTML standard, où de nouvelles balises peuvent être introduites.
Exécuter une charge utile JavaScript
Dans cette dernière étape, vous combinerez la technique d'évasion avec une charge utile JavaScript malveillante pour réaliser un Cross-Site Scripting.
Maintenant que vous savez comment sortir de la balise <input>, vous pouvez ajouter n'importe quel HTML ou JavaScript valide immédiatement après votre séquence d'évasion. La preuve de concept la plus courante pour le XSS est l'injection d'une balise <script> qui déclenche une boîte d'alerte JavaScript alert().
Notre charge utile complète sera : "><script>alert("XSS")</script>
Voici comment fonctionne la charge utile. La séquence "> sort de l'attribut value et ferme la balise <input>. Ensuite, la balise <script> démarre un nouveau bloc d'exécution JavaScript. À l'intérieur de ce bloc, alert("XSS") est le code JavaScript qui sera exécuté. Enfin, la balise </script> ferme le bloc d'exécution.
Exécutez la commande suivante pour injecter la charge utile XSS complète :
curl -s 'http://localhost:8080/search?q="><script>alert("XSS")</script>'
Examinez la sortie HTML finale :
<!DOCTYPE html>
<html>
<head><title>Search Results</title></head>
<body>
<h2>Search Results</h2>
<form action="/search" method="GET">
<input type="text" name="q" value=""><script>alert("XSS")</script>">
<button type="submit">Search Again</button>
</form>
</body>
</html>
Si une victime cliquait sur un lien contenant cette charge utile dans son navigateur web (par exemple, http://localhost:8080/search?q="><script>alert("XSS")</script>), son navigateur analyserait le HTML de haut en bas. Lorsqu'il atteint la balise <script> injectée, il exécute le code JavaScript, faisant apparaître une boîte d'alerte indiquant "XSS".
Dans une attaque réelle, au lieu d'une alerte inoffensive, un attaquant injecterait du code pour voler les cookies de session de la victime (document.cookie) et les envoyer à un serveur malveillant, menant à une prise de contrôle totale du compte.
Résumé
Félicitations ! Vous avez terminé avec succès le laboratoire sur le Cross-Site Scripting (XSS) réfléchi.
Dans ce laboratoire, vous avez appris à :
- Identifier les points de réflexion en envoyant des chaînes uniques et en analysant la réponse HTTP.
- Tester le filtrage des caractères pour déterminer si une application encode correctement les caractères HTML spéciaux.
- Sortir des contextes d'attributs HTML en manipulant les guillemets et les crochets.
- Construire et injecter une charge utile JavaScript complète pour obtenir l'exécution de code dans le navigateur.
Comprendre ces mécanismes est essentiel, tant pour identifier les vulnérabilités en tant que chercheur en sécurité que pour mettre en œuvre un assainissement des entrées et un encodage des sorties appropriés en tant que développeur.



