Sécurité web : bonnes pratiques couche par couche (2026)

Advertisement
Ce que recouvre vraiment la sécurité web
Les bonnes pratiques de sécurité web désignent l'ensemble des contrôles qui empêchent un site ou une application web d'être piraté, défiguré, utilisé pour attaquer ses propres visiteurs ou discrètement vidé de ses données. Il ne s'agit ni d'un produit unique ni d'un simple réglage, mais d'une pile de décisions qui commence chez le registrar du domaine et traverse le DNS, le TLS, les en-têtes HTTP envoyés par votre serveur, le code qui gère les connexions et les entrées utilisateur, les paquets tiers sur lesquels vous bâtissez, le serveur lui-même et, pour finir, les journaux qui vous signalent qu'un problème est survenu.
Si l'on raisonne par couches, c'est parce que les attaquants le font. Le 2026 Data Breach Investigations Report de Verizon montre que 31 % des violations de données commencent désormais par l'exploitation d'une vulnérabilité logicielle, qui dépasse ainsi pour la première fois les identifiants volés comme principal point d'entrée, et que 48 % de toutes les violations impliquent un ransomware. Un seul correctif manquant, une clé d'API divulguée ou une page d'administration sans limitation de débit suffit. Aucun des contrôles de ce guide n'est exotique : les sites piratés sont généralement ceux qui ont négligé les bases sur une couche tout en peaufinant une autre.
Ce guide va de l'extérieur vers l'intérieur. Pour chaque pratique, il vous explique pourquoi elle compte, ce qu'il faut configurer exactement et comment le vérifier avec une commande ou un outil gratuit. En effet, l'erreur la plus fréquente que nous observons dans les vérifications d'en-têtes HTTP et les vérifications SSL n'est pas une mauvaise décision, mais un réglage que quelqu'un croyait activé sans jamais l'avoir confirmé.
La pile de sécurité web : six couches à protéger
Toute attaque contre un site web vise l'une de ces six couches. Le tableau ci-dessous sert de carte pour la suite du guide : ce que contient chaque couche, comment elle est généralement attaquée et quelle vérification gratuite confirme que votre défense est bien en place.
| Couche | Ce que font les attaquants | Pratiques essentielles | Vérifier avec |
|---|---|---|---|
| 1. Domaine et DNS | Détourner le domaine, modifier les serveurs de noms, s'emparer de sous-domaines orphelins, obtenir des certificats frauduleux | Registrar lock, MFA, DNSSEC, CAA, audit des enregistrements obsolètes | Recherche WHOIS, Recherche DNS, Recherche de Sous-domaines |
| 2. Transport (TLS) | Rétrograder vers HTTP, retirer le chiffrement, exploiter d'anciennes suites de chiffrement, profiter de certificats expirés | TLS 1.2+, HSTS avec preload, renouvellement automatisé | Vérification du Certificat SSL |
| 3. En-têtes HTTP | Injecter des scripts (XSS), piéger le site dans un cadre (clickjacking), exploiter le MIME sniffing, faire fuiter le référent | CSP, frame-ancestors, nosniff, Referrer-Policy, Permissions-Policy | Vérification des En-têtes HTTP |
| 4. Application | Credential stuffing, injection, contrôle d'accès défaillant, CSRF, uploads non sécurisés | Argon2id + MFA + limitation de débit, requêtes paramétrées, autorisation côté serveur, cookies SameSite | Revue de code, OWASP ZAP, Test de Force de Mot de Passe |
| 5. Dépendances | Paquets empoisonnés, CVE connues dans les bibliothèques, pipelines CI compromis | Lockfiles, audits, versions épinglées, SBOM, jetons à privilèges minimaux | npm audit, Dependabot, Trivy |
| 6. Serveur et exploitation | Ports ouverts, identifiants par défaut, correctifs manquants, aucune sauvegarde, aucun journal | Pare-feu, SSH par clé uniquement, correctifs, sauvegardes 3-2-1, journalisation centralisée | Vérificateur de Ports, Vérification de Liste Noire IP, Vérificateur de Santé du Domaine |
Advertisement
Couche 1 : verrouiller le domaine et le DNS
Tout le reste de ce guide suppose que vous contrôlez toujours votre domaine. Si un attaquant peut se connecter à votre compte chez le registrar ou modifier vos serveurs de noms, il peut rediriger votre trafic où il veut, obtenir un certificat valide pour votre nom et lire chaque e-mail qui vous est adressé, sans que votre code applicatif ne s'exécute jamais. La sécurité du domaine et du DNS est donc la première bonne pratique de sécurité web, et elle relève presque entièrement de la configuration.
Commencez par une recherche WHOIS sur votre propre domaine et vérifiez trois choses : les codes de statut incluent clientTransferProhibited, la date d'expiration est à plus d'un an et le registrar est bien un registrar chez qui vous avez réellement un compte. Il est étonnamment fréquent qu'un domaine d'entreprise se trouve dans le compte registrar d'un ancien prestataire. Notre guide de la recherche WHOIS explique chaque code de statut que vous rencontrerez.
Registrar lock, MFA et alertes d'expiration
Activez le registrar lock (aussi appelé verrou de transfert) afin que le domaine ne puisse pas être transféré vers un autre registrar sans que vous le déverrouilliez explicitement, et activez l'authentification multifacteur sur le compte registrar lui-même. Les comptes registrar sont une cible de phishing privilégiée précisément parce qu'un seul identifiant contrôle tout ce qui en dépend. Utilisez une clé matérielle ou une application d'authentification plutôt que le SMS dès que le registrar le permet.
Configurez le renouvellement automatique du domaine avec un moyen de paiement qui n'expirera pas, et ajoutez malgré tout une alerte dans votre agenda 60 jours avant la date d'expiration. Les domaines expirés sont récupérés par des drop-catchers en quelques heures, et l'acheteur hérite de vos e-mails, de votre trafic et de toutes les connexions OAuth qui font confiance à votre domaine.
Le registry lock (un verrou manuel, hors bande, au niveau du registre) vaut le surcoût pour un domaine dont dépend une entreprise : il empêche même un compte registrar compromis de modifier les serveurs de noms.
Séparez les rôles. La personne qui paie le domaine, le compte qui le détient et le fournisseur DNS doivent chacun être documentés et ne pas dépendre de la boîte mail d'un seul employé.
Activez la confidentialité WHOIS pour que vos coordonnées ne servent pas de carte aux campagnes de phishing, et gardez sur le compte une adresse de rôle surveillée comme
domains@.
Signer la zone avec DNSSEC
DNSSEC signe votre zone DNS afin qu'un résolveur puisse détecter les réponses falsifiées. Sans lui, un attaquant capable d'empoisonner le cache d'un résolveur peut envoyer vos visiteurs vers un faux serveur alors que leur navigateur affiche toujours votre nom de domaine. La plupart des fournisseurs DNS managés (Cloudflare, Route 53, Google Cloud DNS et de nombreux registrars) l'activent d'un simple clic ; la seule étape manuelle consiste à publier l'enregistrement DS chez votre registrar. Vérifiez-le avec dig, ou avec le contrôle DNSSEC intégré au Vérificateur de Santé du Domaine :
dig +dnssec +short yourdomain.com A
# A signed zone returns the record AND an RRSIG line:
# 203.0.113.10
# A 13 2 3600 20261015000000 20260924000000 34505 yourdomain.com. Kx3f...==
dig +short yourdomain.com DS
# A DS record at the parent zone proves the chain of trust is complete
# 34505 13 2 6A1B...C9Restreindre l'émission de certificats avec CAA
Un enregistrement CAA (RFC 8659) indique aux autorités de certification lesquelles d'entre elles peuvent émettre des certificats pour votre domaine. Toute AC publique est tenue de le vérifier avant d'émettre, si bien qu'un enregistrement CAA ferme la porte à un attaquant qui aurait trompé la validation de domaine d'une autre AC. Trois enregistrements couvrent les cas courants : qui peut émettre, qui peut émettre des certificats wildcard et où signaler une demande refusée :
yourdomain.com. CAA 0 issue "letsencrypt.org"
yourdomain.com. CAA 0 issuewild ";"
yourdomain.com. CAA 0 iodef "mailto:security@yourdomain.com"Auditer les enregistrements obsolètes : subdomain takeover
Un subdomain takeover (prise de contrôle de sous-domaine) se produit lorsqu'un enregistrement DNS pointe encore vers un service que vous n'utilisez plus : un CNAME vers un site GitHub Pages supprimé, une application Azure, un bucket S3 ou le nom d'hôte d'un fournisseur SaaS. N'importe qui peut enregistrer la cible abandonnée, puis servir du contenu sur old-app.yourdomain.com en votre nom, certificat valide compris. C'est l'une des découvertes les plus fréquentes des programmes de bug bounty, car personne ne se souvient que l'enregistrement existe.
Passez votre domaine dans la Recherche de Sous-domaines, qui lit les journaux Certificate Transparency : vous voyez ainsi tous les noms d'hôte pour lesquels un certificat a déjà été émis. Résolvez ensuite chacun d'eux avec une recherche DNS et supprimez tout enregistrement dont la cible renvoie NXDOMAIN ou une page « no such app » d'un fournisseur. Recommencez chaque trimestre et intégrez la suppression de l'enregistrement DNS au démantèlement de chaque service.
Couche 2 : HTTPS et TLS bien configurés
HTTPS n'est plus une bonne pratique : c'est le strict minimum, et les navigateurs marquent les pages en HTTP simple comme « Non sécurisé ». Ce qui distingue encore un site sécurisé d'un site simplement chiffré, ce sont les versions de TLS que vous acceptez, le fait qu'on puisse ou non vous joindre en HTTP, et un renouvellement suffisamment automatisé pour résister à la réduction de la durée de vie des certificats entamée en mars 2026.
Advertisement
TLS 1.2 au minimum, TLS 1.3 de préférence
TLS 1.0 et 1.1 ont été officiellement dépréciés par la RFC 8996 en 2021, et aucun navigateur actuel ne les négocie. Désactivez-les sur le serveur, privilégiez TLS 1.3 (qui supprime toutes les suites de chiffrement réputées faibles et termine la négociation en un seul aller-retour) et ne conservez TLS 1.2 qu'avec des suites AEAD comme ECDHE-ECDSA-AES128-GCM-SHA256 ou ECDHE-RSA-CHACHA20-POLY1305.
Deux lignes comptent quand vous testez depuis l'extérieur : le protocole négocié, et Verify return code: 0, qui signifie que toute la chaîne de certificats a été validée. Un certificat intermédiaire manquant est la cause la plus fréquente des signalements du type « ça marche dans Chrome, mais pas avec curl ni sur Android » ; notre guide sur la chaîne de certificats SSL explique comment corriger le problème, et la Vérification du Certificat SSL signale directement une chaîne incomplète. Voici le test exécuté sur dnsrobot.net :
echo | openssl s_client -connect dnsrobot.net:443 -servername dnsrobot.net 2>/dev/null \
| grep -E 'Protocol|Cipher|Verify return'
# Protocol : TLSv1.3
# Cipher : TLS_AES_256_GCM_SHA384
# Verify return code: 0 (ok)
# Confirm the old versions are refused:
openssl s_client -connect dnsrobot.net:443 -tls1_1 2>&1 | grep -iE 'alert|no protocols'HSTS : ne plus jamais laisser un navigateur utiliser HTTP
Rediriger HTTP vers HTTPS ne suffit pas à lui seul. La toute première requête d'un visiteur vers http://yourdomain.com circule toujours en clair, et un attaquant présent sur le même réseau peut y répondre avant votre redirection. HTTP Strict Transport Security (RFC 6797) règle ce problème : dès qu'un navigateur a vu l'en-tête, il réécrit chaque future URL http:// de votre domaine en https:// avant d'envoyer quoi que ce soit.
Utilisez un max-age d'au moins un an (31536000 secondes), ajoutez includeSubDomains dès que tous vos sous-domaines servent du HTTPS, puis soumettez le domaine sur hstspreload.org pour qu'il soit codé en dur dans Chrome, Firefox, Safari et Edge. Le préchargement élimine complètement la faille de la première visite. Vérifiez l'en-tête avec la Vérification des En-têtes HTTP, qui note HSTS dans son score de sécurité de A à F.
Strict-Transport-Security: max-age=31536000; includeSubDomains; preloadCertificats de 47 jours : automatisez le renouvellement dès maintenant
Le vote SC-081 du CA/Browser Forum réduit par étapes la durée de vie maximale de tout certificat TLS public. La première réduction est entrée en vigueur le 15 mars 2026 : tout certificat acheté ou renouvelé aujourd'hui est donc déjà limité à 200 jours, et d'ici 2029 il faudra remplacer un certificat environ toutes les six semaines :
| Date d'entrée en vigueur | Validité maximale du certificat | Réutilisation de la validation de domaine |
|---|---|---|
| Avant le 15 mars 2026 | 398 jours | 398 jours |
| 15 mars 2026 | 200 jours | 200 jours |
| 15 mars 2027 | 100 jours | 100 jours |
| 15 mars 2029 | 47 jours | 10 jours |
Un renouvellement manuel ne tient pas face à ce calendrier. La bonne pratique consiste à automatiser entièrement l'émission via ACME : Let's Encrypt ou Google Trust Services avec certbot, acme.sh ou Caddy, ou encore les certificats automatiques intégrés à Cloudflare, Vercel, Netlify et à la plupart des panneaux d'hébergement. Testez la procédure de renouvellement avant d'en avoir besoin (certbot renew --dry-run pour certbot) ; l'échec à surveiller est un enregistrement CAA ou une règle de pare-feu ajoutés depuis le dernier renouvellement et qui bloquent désormais la validation. Quelle que soit votre solution, surveillez aussi la date d'expiration depuis l'extérieur : la Vérification du Certificat SSL affiche le nombre de jours restants, et un certificat expiré transforme chaque visite en avertissement plein écran du navigateur.
Couche 3 : en-têtes de sécurité HTTP
Les en-têtes de sécurité sont des instructions que votre serveur donne au navigateur sur ce qu'il peut faire ou non avec vos pages : quels scripts peuvent s'exécuter, si la page peut être intégrée dans un cadre, si le navigateur peut deviner les types de contenu et ce qu'il doit dire aux autres sites sur la provenance d'un visiteur. Ils ne coûtent rien, s'appliquent à toutes les pages à la fois et bloquent des catégories entières d'attaques. C'est aussi la couche que la plupart des sites configurent à moitié, et c'est pourquoi la Vérification des En-têtes HTTP leur attribue une note. Voici ce qu'envoie dnsrobot.net, limité aux en-têtes de sécurité :
curl -sI https://dnsrobot.net/ | grep -iE 'strict-transport|content-security|x-frame|x-content-type|referrer-policy|permissions-policy'
strict-transport-security: max-age=31536000; includeSubDomains; preload
content-security-policy: default-src 'self'; script-src 'self' ... https://*.googletagmanager.com; frame-ancestors 'none'; base-uri 'self'; form-action 'self'
x-frame-options: DENY
x-content-type-options: nosniff
referrer-policy: strict-origin-when-cross-origin
permissions-policy: camera=(self), microphone=(), geolocation=(), payment=(), usb=()Les sept en-têtes que tout site devrait envoyer
Voici les valeurs à viser pour un site classique. Les cinq premiers sont ceux qui font évoluer votre note ; les deux derniers sont des ajouts peu coûteux une fois les autres en place.
| En-tête | Valeur recommandée | Ce qu'il empêche |
|---|---|---|
Strict-Transport-Security | max-age=31536000; includeSubDomains; preload | Rétrogradation de protocole, vol de cookies via HTTP |
Content-Security-Policy | script-src à base de nonce avec 'strict-dynamic' ; object-src 'none' ; base-uri 'none' ; frame-ancestors 'none' | Cross-site scripting (XSS), injection de données, clickjacking |
X-Content-Type-Options | nosniff | Le MIME sniffing qui transforme un fichier uploadé en script exécutable |
Referrer-Policy | strict-origin-when-cross-origin | Fuite d'URL complètes (jetons, termes de recherche) vers des tiers |
Permissions-Policy | camera=(), microphone=(), geolocation=(), payment=() | Scripts tiers qui utilisent en silence des API puissantes du navigateur |
X-Frame-Options | DENY (repli historique pour frame-ancestors) | Clickjacking dans les navigateurs sans CSP Level 2 |
Cross-Origin-Opener-Policy | same-origin | Attaques inter-fenêtres via window.opener |
Content Security Policy sans casser le site
Une Content Security Policy est la défense la plus efficace contre le XSS, car elle empêche les scripts injectés de s'exécuter même lorsqu'une faille d'injection existe. Le revers : une politique stricte casse tout script inline ou toute balise tierce que vous auriez oubliés. L'approche moderne, recommandée par Google et documentée sur MDN, est une politique à base de nonce : le serveur génère un nonce aléatoire pour chaque réponse, le place sur chaque balise script qu'il affiche volontairement, et le navigateur refuse tout le reste.
C'est 'strict-dynamic' qui rend la politique utilisable en pratique : un script doté d'un nonce peut charger d'autres scripts (analytics, gestionnaires de balises, widgets) sans que chacun doive figurer sur une liste d'autorisation, tandis que les jetons https: et 'unsafe-inline' sont ignorés par les navigateurs modernes et ne servent que de repli pour les anciens. Déployez d'abord avec Content-Security-Policy-Report-Only, surveillez les rapports de violation pendant une semaine, puis passez en mode bloquant. Des frameworks comme Next.js, Rails et Django prennent en charge les nonces nativement ; les sites statiques peuvent utiliser à la place un script-src à base de hash.
Content-Security-Policy:
script-src 'nonce-r4nd0m1z3dV4lu3' 'strict-dynamic' https: 'unsafe-inline';
object-src 'none';
base-uri 'none';
frame-ancestors 'none';
form-action 'self';
report-to csp-endpoint
<!-- Only scripts carrying the nonce run; strict-dynamic lets them load their own dependencies -->
<script nonce="r4nd0m1z3dV4lu3" src="/app.js"></script>Clickjacking : frame-ancestors et X-Frame-Options
Le clickjacking charge votre site de façon invisible dans la page d'un attaquant et pousse le visiteur à cliquer sur un bouton qu'il ne voit pas. frame-ancestors 'none' dans la CSP (ou 'self' si vous intégrez vos propres pages) l'empêche dans tous les navigateurs actuels, et X-Frame-Options: DENY couvre les plus anciens. Si vous proposez volontairement un widget intégrable, n'exemptez que ce chemin et uniquement pour les origines qui en ont besoin ; notre guide X-Frame-Options détaille les règles serveur exactes et les erreurs « refused to connect » que vous rencontrerez pendant vos tests.
nosniff, Referrer-Policy, Permissions-Policy et COOP
X-Content-Type-Options: nosniff empêche le navigateur de remettre en cause un Content-Type, ce qui est précisément ce qui transforme une « image » contenant du HTML, uploadée par un utilisateur, en page exécutable. Referrer-Policy: strict-origin-when-cross-origin (le comportement par défaut des navigateurs actuels, mais définissez-le explicitement) n'envoie que votre origine aux autres sites, si bien que les jetons de réinitialisation de mot de passe et les requêtes de recherche présents dans les URL restent privés. Permissions-Policy désactive les fonctionnalités du navigateur que vous n'utilisez pas, pour qu'un script tiers compromis ne puisse ni ouvrir la caméra ni lire la localisation. Cross-Origin-Opener-Policy: same-origin coupe le lien window.opener vers les pages que vous ouvrez, ce qui bloque toute une catégorie d'attaques inter-fenêtres.
Les en-têtes à supprimer comptent aussi : Server et X-Powered-By affichent les versions exactes de vos logiciels aux scanners de vulnérabilités, et X-XSS-Protection est obsolète et peut provoquer des bugs dans les anciens navigateurs ; réglez-le donc sur 0 ou retirez-le. Le Détecteur de CMS montre ce qu'un scanner apprend de votre stack à partir des seuls en-têtes.
Couche 4 : une authentification qui résiste au credential stuffing
Les attaquants devinent rarement les mots de passe un par un. Ils rejouent des milliards de couples e-mail/mot de passe divulgués par d'autres sites (credential stuffing) et obtiennent le reste par phishing. Les bonnes pratiques d'authentification comportent donc trois volets : stocker les mots de passe de sorte qu'une fuite de base de données ne soit pas une fuite de mots de passe, rendre un mot de passe volé inutilisable à lui seul, et rendre la force brute trop lente pour être efficace. L'OWASP classe les Authentication Failures (défaillances d'authentification) en A07 dans l'OWASP Top 10:2025.
Advertisement
Hacher les mots de passe avec Argon2id ou bcrypt
Ne stockez jamais un mot de passe, ni même un hash rapide de celui-ci. MD5, SHA-1 et même SHA-256 sont conçus pour être rapides : une table divulguée de ces hashs peut être testée à raison de milliards de tentatives par seconde sur un seul GPU. Utilisez une fonction de hachage de mots de passe lente et gourmande en mémoire avec un sel unique par mot de passe. L'OWASP Password Storage Cheat Sheet recommande, dans l'ordre :
Argon2id avec au moins 19 Mio de mémoire, 2 itérations et un degré de parallélisme de 1 (ou 46 Mio avec 1 itération).
scrypt avec N = 2^17, r = 8, p = 1 lorsque Argon2 n'est pas disponible.
bcrypt avec un facteur de coût de 10 ou plus (attention à sa limite d'entrée de 72 octets ; le pré-hachage des mots de passe plus longs demande des précautions).
PBKDF2-HMAC-SHA256 avec 600 000 itérations, uniquement lorsque la conformité FIPS l'impose.
// Node.js with the argon2 package
import argon2 from "argon2";
const hash = await argon2.hash(password, {
type: argon2.argon2id,
memoryCost: 19456, // KiB = 19 MiB
timeCost: 2,
parallelism: 1,
});
// Later, on login:
const ok = await argon2.verify(hash, submittedPassword);Des règles de mot de passe vraiment utiles (NIST SP 800-63B)
Les règles de composition que la plupart des sites imposent encore (une majuscule, un symbole, un changement tous les 90 jours) produisent des mots de passe prévisibles comme Summer2026! et poussent les gens à les réutiliser. Les recommandations actuelles du NIST SP 800-63B les remplacent par des règles qui mesurent ce qui compte vraiment :
Au minimum 8 caractères lorsque la MFA est également exigée, et au moins 15 caractères pour un mot de passe utilisé seul ; autorisez-en au moins 64.
Aucune règle de composition et aucune rotation périodique forcée ; n'exigez un changement qu'en cas de preuve de compromission.
Vérifiez chaque nouveau mot de passe dans une liste de fuites (l'API par plage de Have I Been Pwned permet de le faire sans envoyer le mot de passe) et refusez ceux qui ont déjà fuité.
Autorisez le copier-coller et les gestionnaires de mots de passe, acceptez les espaces et l'Unicode, et affichez un indicateur de robustesse fondé sur l'entropie plutôt que sur des règles.
Notre Test de Force de Mot de Passe montre en quoi ces critères diffèrent des anciennes règles : il estime le temps de cassage à partir de l'entropie et de la détection de motifs, et vérifie le mot de passe dans des données de fuites, ce qui est bien plus utile qu'un message rouge « symbole requis ».
MFA et passkeys
L'authentification multifacteur transforme un mot de passe volé en impasse. Proposez-la à tout le monde et exigez-la pour les rôles d'administration, de finance et de support. Classez les options selon leur résistance au phishing : les passkeys et clés de sécurité FIDO2 ne peuvent pas être hameçonnées, car l'identifiant est lié à votre véritable origine ; les applications d'authentification (TOTP) sont une bonne option ; les codes SMS valent mieux que rien, mais peuvent être interceptés par SIM swapping. Les passkeys sont prises en charge par tous les navigateurs et systèmes d'exploitation actuels et suppriment complètement le mot de passe, ce qui élimine du même coup toute la catégorie du credential stuffing.
Protégez la procédure de récupération avec autant de soin que la connexion : codes de récupération stockés sous forme hachée, réinitialisations par e-mail avec des jetons à usage unique qui expirent en 15 minutes, et aucune question de sécurité.
Limitation de débit, verrouillage et défense anti-bots
Appliquez une limitation de débit aux endpoints de connexion, d'inscription, de réinitialisation de mot de passe et de MFA, par IP et par compte, et renvoyez 429 Too Many Requests avec un en-tête Retry-After une fois la limite atteinte (notre guide sur l'erreur HTTP 429 explique comment les clients doivent réagir). Combinez-la avec un délai croissant ou un verrouillage temporaire après des échecs répétés sur un même compte, et avec un CAPTCHA ou un défi proof-of-work pour les endpoints visés par des attaques distribuées. Journalisez chaque échec de connexion avec l'IP source, afin que le schéma d'une campagne de credential stuffing soit visible en quelques minutes plutôt qu'en quelques mois.
# nginx: 5 login attempts per minute per client IP
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
location = /api/login {
limit_req zone=login burst=4 nodelay;
limit_req_status 429;
proxy_pass http://app;
}Sessions, cookies et CSRF
Après la connexion, le cookie de session est l'utilisateur ; il mérite donc la même protection que le mot de passe. Trois attributs de cookie et un préfixe de nom font l'essentiel du travail :
Securesignifie que le cookie n'est jamais envoyé en HTTP simple ; il ne peut donc pas être intercepté sur un Wi-Fi public.HttpOnlyle rend invisible pour JavaScript, si bien qu'une faille XSS ne peut pas le lire.SameSite=Lax(ouStrictpour les panneaux d'administration) l'exclut des requêtes POST intersites, ce qui neutralise la plupart des attaques CSRF.Le préfixe
__Host-amène le navigateur à refuser le cookie s'il n'est pasSecure, s'il n'a pasPath=/ou s'il possède un attributDomain, si bien qu'un sous-domaine ne peut pas l'écraser.
Set-Cookie: __Host-session=9f1c7e2a...; Path=/; Secure; HttpOnly; SameSite=Lax; Max-Age=28800CSRF : une seconde ligne de défense derrière SameSite
Le cross-site request forgery (CSRF) pousse un navigateur connecté à envoyer à votre site, depuis une autre page, une requête qui modifie un état. Les cookies SameSite bloquent le cas courant, mais conservez une seconde défense sur chaque requête non-GET : un jeton anti-CSRF par session dans un champ caché ou un en-tête personnalisé, ou une vérification que l'en-tête Origin (ou Sec-Fetch-Site) correspond bien à votre propre origine. La plupart des frameworks (Django, Rails, Laravel, les server actions de Next.js) le font par défaut ; l'erreur consiste à désactiver cette protection pour un endpoint d'API, puis à appeler cet endpoint depuis un navigateur.
ID de session, rotation et JWT
Générez des identifiants de session avec au moins 128 bits d'aléa, changez l'identifiant à la connexion et à chaque changement de privilèges pour déjouer la fixation de session, faites expirer les sessions après une période d'inactivité et offrez aux utilisateurs un bouton « se déconnecter partout » qui les invalide côté serveur. Pour les JWT, gardez-les de courte durée (quelques minutes, avec un refresh token révocable), ne les stockez jamais dans localStorage où n'importe quel script peut les lire, et traitez la fuite d'une clé de signature comme une compromission totale, car chaque jeton qu'elle a signé devient falsifiable.
Injection et XSS : valider les entrées, encoder les sorties
L'injection (A05:2025) et le cross-site scripting sont la même erreur commise à des endroits différents : des données fournies par un utilisateur sont transmises à un interpréteur (SQL, le shell, une requête LDAP, une page HTML) comme s'il s'agissait de code. La correction est partout la même : séparer les données du code et ne jamais construire une commande par concaténation de chaînes.
Advertisement
Des requêtes paramétrées, pas de concaténation
Pour SQL, utilisez des requêtes préparées ou un ORM qui les génère : la base de données traite alors l'entrée comme une valeur qui ne peut jamais modifier la structure de la requête. La même règle s'applique aux commandes shell (passez un tableau d'arguments, jamais une chaîne), aux filtres NoSQL (rejetez les objets opérateurs comme {"$gt": ""} dans les entrées utilisateur) et aux chemins de fichiers (résolvez le chemin et vérifiez qu'il reste sous le répertoire prévu).
// Vulnerable: the input becomes part of the query text
const rows = await db.query(`SELECT * FROM users WHERE email = '${email}'`);
// Safe: the driver sends the value separately from the query
const rows = await db.query("SELECT * FROM users WHERE email = $1", [email]);
// Python / psycopg: same idea
cur.execute("SELECT * FROM users WHERE email = %s", (email,))L'encodage des sorties arrête le XSS
Le cross-site scripting se produit lorsqu'un texte contrôlé par l'utilisateur est écrit dans une page sans être encodé pour le contexte où il atterrit. Les moteurs de templates modernes (React et JSX, Vue, Jinja2, Blade, ERB) encodent par défaut ; aujourd'hui, le XSS vient généralement des échappatoires : dangerouslySetInnerHTML, v-html, |safe, innerHTML, et la construction d'URL ou de gestionnaires d'événements inline à partir de données utilisateur. Encodez pour le contexte exact et nettoyez le HTML riche avec une bibliothèque dédiée comme DOMPurify plutôt qu'avec une regex.
| Où arrivent les données | Encoder en | Exemple |
|---|---|---|
| Corps HTML | Entités HTML | < devient <, " devient " |
| Attribut HTML | Entités pour attributs entre guillemets | Mettez toujours l'attribut entre guillemets ; encodez " et ' |
| JavaScript | N'injectez rien dans le texte du script ; transmettez les données via des attributs data- ou un bloc JSON <script type="application/json"> | </script> dans une chaîne devient \u003c/script\u003e |
| Paramètre d'URL | Encodage-pourcent (percent-encoding) | encodeURIComponent(value) |
| Valeur CSS | À éviter totalement ; choisissez les noms de classes dans une liste d'autorisation | N'interpolez jamais d'entrée utilisateur dans style |
SSRF, uploads de fichiers et désérialisation
Server-side request forgery (SSRF) : si votre serveur récupère une URL fournie par un utilisateur (webhooks, proxys d'images, aperçus de liens), un attaquant peut la faire pointer vers des services internes ou vers l'endpoint de métadonnées cloud 169.254.169.254 et y lire des identifiants. Résolvez d'abord le nom d'hôte, rejetez les plages privées et link-local, désactivez les redirections et placez les composants chargés de ces requêtes sur un segment réseau qui ne peut rien atteindre en interne.
Uploads de fichiers : validez le type en inspectant le contenu, et non l'extension ou le Content-Type envoyé par le client ; imposez une limite de taille ; stockez les fichiers hors de la racine web ou dans un stockage objet, sous un nom aléatoire que vous générez ; et servez-les depuis une origine distincte avec nosniff et Content-Disposition: attachment lorsque c'est possible. Ne laissez jamais un upload atterrir à un endroit où le serveur web l'exécutera.
Désérialisation et mass assignment : ne désérialisez jamais de données non fiables avec un format capable d'instancier des classes arbitraires (sérialisation native Java, pickle en Python, unserialize en PHP, YAML avec des tags personnalisés) ; utilisez du JSON avec un schéma. Liez les corps de requête à une liste explicite de champs autorisés, afin qu'un utilisateur ne puisse pas envoyer "role": "admin" par POST dans un modèle qui possède justement cette colonne.
Broken Access Control : le risque numéro un
Le Broken Access Control (contrôle d'accès défaillant) occupe la première place de l'OWASP Top 10 depuis 2021 et la conserve en A01:2025. Ce n'est pas un bug isolé mais une habitude : vérifier qui est quelqu'un (authentification) et oublier de vérifier ce qu'il a le droit de toucher (autorisation) à chaque requête. La forme classique est l'insecure direct object reference (référence directe non sécurisée à un objet) : GET /api/invoices/1042 fonctionne pour le propriétaire de la facture, mais aussi pour quiconque modifie le numéro.
Refusez par défaut. Chaque route exige une règle explicite accordant l'accès ; une règle manquante signifie 403, pas 200.
Contrôlez côté serveur, objet par objet. Masquer un bouton dans l'interface n'est pas du contrôle d'accès. Chaque lecture et chaque écriture doit confirmer que l'utilisateur courant possède l'enregistrement concerné ou y est autorisé, y compris dans les endpoints groupés, les exports et les tâches en arrière-plan.
Utilisez des identifiants impossibles à deviner quand c'est utile (UUID), mais ne comptez jamais dessus : l'obscurité n'est pas une autorisation.
Verrouillez CORS.
Access-Control-Allow-Origin: *avec des identifiants, ou le renvoi de n'importe quelOriginenvoyé par la requête, livre votre API à tout site web visité par l'utilisateur.Désactivez le listing des répertoires, bloquez
.git,.env, les fichiers de sauvegarde et de configuration au niveau du serveur web, et gardez les panneaux d'administration hors de l'internet public ou derrière la MFA et des listes d'IP autorisées.Limitez le débit et journalisez les échecs d'autorisation. Une rafale de 403 depuis une même session, c'est une attaque par énumération en cours.
// Express: ownership check on every object access
app.get("/api/invoices/:id", requireAuth, async (req, res) => {
const invoice = await Invoice.findById(req.params.id);
if (!invoice || invoice.ownerId !== req.user.id) {
return res.status(404).end(); // 404, not 403: don't confirm the record exists
}
res.json(invoice);
});Couche 5 : dépendances et chaîne d'approvisionnement logicielle
Une application web typique embarque peut-être 5 % de code que vous avez écrit et 95 % de code que vous avez téléchargé. C'est pourquoi les Software Supply Chain Failures (défaillances de la chaîne d'approvisionnement logicielle) font leur entrée en A03 dans l'OWASP Top 10 2025, et pourquoi l'exploitation de vulnérabilités a dépassé les identifiants volés dans le DBIR 2026. En septembre 2025, un seul mainteneur victime de phishing a introduit un malware de vol de cryptomonnaies dans chalk, debug et 16 autres paquets npm totalisant plus de deux milliards de téléchargements par semaine ; tout projet ayant installé une version non épinglée pendant cette fenêtre l'a récupéré automatiquement.
Commitez un lockfile (
package-lock.json,yarn.lock,pnpm-lock.yaml,poetry.lock,go.sum) et installez avecnpm cien CI, pour que les builds soient reproductibles et qu'une nouvelle version publiée en amont ne puisse pas s'infiltrer sans relecture.Analysez en continu :
npm audit,pip-audit,bundler-audit, GitHub Dependabot ou Renovate pour les mises à jour, et un scanner de conteneurs comme Trivy ou Grype pour la couche système.Retardez de quelques jours les mises à jour non liées à la sécurité (
minimumReleaseAgede Renovate), pour qu'une version empoisonnée soit généralement retirée avant que vous ne l'adoptiez, mais appliquez immédiatement les correctifs de sécurité.Épinglez les actions et scripts tiers sur un SHA de commit en CI, et utilisez Subresource Integrity (
integrity="sha384-...") pour tout script chargé depuis un CDN public.Accordez à la CI le moindre privilège : jetons en lecture seule lorsque c'est possible, identifiants OIDC de courte durée plutôt que des secrets à longue durée de vie, et droits de publication réservés à un job de release.
Générez un SBOM (CycloneDX ou SPDX) au moment du build, pour pouvoir répondre en quelques minutes à la question « sommes-nous concernés ? » quand tombera la prochaine CVE du calibre de Log4Shell.
# Reproducible install + audit in CI
npm ci --ignore-scripts
npm audit --audit-level=high
# Pin a GitHub Action to a commit, not a floating tag
# uses: actions/checkout@v4 <- can change underneath you
# uses: actions/checkout@<full-commit-sha> # v4.2.2
# Subresource Integrity for a CDN script (hash from: openssl dgst -sha384 -binary lib.min.js | openssl base64 -A)
<script src="https://cdn.example.com/lib.min.js"
integrity="sha384-<base64-hash>"
crossorigin="anonymous"></script>Si vous utilisez WordPress ou un autre CMS, les mêmes règles s'appliquent aux plugins et aux thèmes, par lesquels commencent la plupart des compromissions de CMS. Maintenez le cœur et chaque plugin à jour, supprimez ceux que vous n'utilisez pas et vérifiez ce qu'un scanner peut apprendre de vos versions avec le Détecteur de CMS.
Couche 6 : durcissement du serveur (ports, correctifs, secrets, sauvegardes)
La couche applicative ne sert à rien si le serveur sous-jacent accepte les connexions SSH par mot de passe, expose une base de données sur un port public ou n'a pas été mis à jour depuis son installation. Les bonnes pratiques côté serveur sont ennuyeuses, et c'est précisément par là que les ransomwares entrent.
Fermer chaque port que vous n'utilisez pas
Un serveur web public a besoin des ports 80 et 443 ouverts, et de SSH depuis votre propre plage d'IP. Les bases de données (3306, 5432, 27017), Redis (6379), Elasticsearch (9200), les panneaux d'administration et les endpoints de métriques doivent écouter uniquement sur localhost ou sur un réseau privé. Vérifiez depuis l'extérieur avec le Vérificateur de Ports après chaque modification, car c'est la vue dont dispose un attaquant, et les groupes de sécurité cloud sont faciles à mal interpréter.
# Ubuntu: default-deny firewall, allow only web + SSH from your office range
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow from 203.0.113.0/24 to any port 22 proto tcp
sudo ufw enable
# SSH: keys only, no root password login
sudo sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config
sudo systemctl reload sshCorriger selon un calendrier, garder les secrets hors du code
Activez les mises à jour de sécurité automatiques du système d'exploitation, abonnez-vous aux listes de sécurité de votre runtime et de votre framework, et traitez une CVE critique sur tout composant exposé à internet comme une tâche à régler dans la journée. Exécutez les services sous des utilisateurs non privilégiés, dans des conteneurs ou avec le sandboxing de systemd, pour qu'un processus compromis ne puisse pas lire toute la machine.
Les secrets (mots de passe de base de données, clés d'API, clés de signature) n'ont leur place ni dans le dépôt, ni dans une couche d'image Docker, ni dans le JavaScript côté client. Chargez-les depuis des variables d'environnement injectées au déploiement ou depuis un gestionnaire de secrets, renouvelez-les lorsqu'une personne qui y avait accès s'en va, et analysez l'historique du dépôt avec un outil comme gitleaks, car une clé commitée une seule fois est compromise pour toujours, même après la suppression du commit.
Des sauvegardes qui résistent aux ransomwares, et un CDN en frontal
Appliquez la règle 3-2-1 : trois copies, sur deux supports différents, dont une hors site, et rendez au moins une copie immuable ou hors ligne, afin qu'un ransomware qui atteint le serveur ne puisse pas chiffrer aussi les sauvegardes. Chiffrez les sauvegardes, incluez la base de données et le répertoire des uploads et surtout, testez une restauration à intervalles réguliers. Une sauvegarde à partir de laquelle personne n'a jamais restauré est un espoir, pas un plan. C'est le temps de reprise qui détermine si un incident sera une simple panne ou un événement fatal pour l'entreprise.
Placez un CDN ou un WAF (Cloudflare, Fastly, AWS CloudFront avec WAF, ou l'équivalent de votre hébergeur) devant l'origine. Il absorbe les DDoS volumétriques, applique des règles managées contre les charges d'injection courantes et les bots malveillants, masque l'IP de votre origine et vous offre un endroit où appliquer limitation de débit et règles géographiques sans toucher à l'application. Restreignez ensuite le pare-feu de l'origine pour que seules les plages d'IP du CDN puissent atteindre directement le port 443 ; sinon, les attaquants le contournent tout simplement. Le Vérificateur d'hébergement indique si l'origine réelle d'un site est exposée derrière son CDN.
Authentification des e-mails : SPF, DKIM et DMARC
La sécurité web englobe aussi les e-mails qui transportent vos réinitialisations de mot de passe, vos factures et vos réponses au support. Sans SPF, DKIM et DMARC, n'importe qui peut envoyer des e-mails en tant que billing@yourdomain.com, et depuis février 2024 Google et Yahoo exigent les trois de la part des expéditeurs en masse. L'ensemble complet tient en trois enregistrements DNS TXT :
yourdomain.com. TXT "v=spf1 include:_spf.google.com -all"
google._domainkey.yourdomain.com. TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkq..."
_dmarc.yourdomain.com. TXT "v=DMARC1; p=reject; rua=mailto:dmarc@yourdomain.com; adkim=s; aspf=s"Démarrez DMARC en p=none pour collecter les rapports, puis passez à p=quarantine et enfin à p=reject une fois que chaque expéditeur légitime (plateforme marketing, helpdesk, CRM) respecte l'alignement. Ajoutez des enregistrements MTA-STS et TLS-RPT pour imposer une livraison chiffrée vers vos serveurs de messagerie, et publiez un MX nul (MX 0 .) sur les domaines qui n'envoient jamais d'e-mails, pour qu'ils ne puissent pas du tout être usurpés. Vérifiez chaque enregistrement avec le Vérificateur d'Enregistrement SPF, le Vérificateur DKIM et le Vérificateur DMARC, et contrôlez vos IP d'envoi dans les listes de blocage avec la Vérification de Liste Noire IP si la délivrabilité chute.
Journaliser, surveiller et anticiper l'intrusion
Deux des dix catégories de l'OWASP 2025 portent sur ce qui se passe après une erreur : Security Logging and Alerting Failures (A09) et la nouvelle catégorie Mishandling of Exceptional Conditions (A10). Une intrusion typique passe encore inaperçue pendant des mois, parce que les preuves n'ont jamais été enregistrées, ou qu'elles l'ont été sans que personne ne les consulte.
Journalisez les événements de sécurité avec leur contexte : chaque connexion réussie ou échouée, les modifications de MFA, les réinitialisations de mot de passe, les changements de permissions, les refus du contrôle d'accès, les échecs de validation des entrées et les actions d'administration, chacun avec l'horodatage, l'ID utilisateur, l'IP source et le user agent.
Ne journalisez jamais de secrets : mots de passe, jetons de session, numéros de carte complets, clés d'API. Masquez-les au niveau de la couche de journalisation, pas à chaque point d'appel.
Envoyez les journaux hors du serveur vers un stockage centralisé (CloudWatch, Loki, Elastic, un SIEM) avec une rétention d'au moins 90 jours, pour qu'un attaquant ayant obtenu les droits root ne puisse pas effacer ses traces.
Déclenchez des alertes sur des schémas, pas sur des événements isolés : 50 échecs de connexion en une minute, un pic de 403 depuis une même session, un nouvel administrateur créé en dehors des heures ouvrées, un certificat émis pour votre domaine que vous n'avez pas demandé.
Échouez en mode fermé (fail closed) : lorsqu'un contrôle en aval (service d'authentification, limiteur de débit, WAF) renvoie une erreur, refusez la requête. La catégorie A10 existe parce que tant de systèmes accordent l'accès lorsque le contrôle qui aurait dû bloquer la requête lève une exception.
Surveillez depuis l'extérieur : disponibilité, expiration des certificats, modifications DNS, inscriptions sur des listes de blocage et régressions d'en-têtes. Le Vérificateur de Santé du Domaine regroupe les contrôles DNS, SSL, d'authentification des e-mails et d'en-têtes en un seul score que vous pouvez relancer après chaque déploiement.
Rédiger le plan de réponse aux incidents avant d'en avoir besoin
Décidez à l'avance qui est d'astreinte, comment renouveler chaque identifiant, comment passer le site en lecture seule, où se trouvent les sauvegardes saines, et quels régulateurs ou clients doivent être notifiés et dans quel délai (72 heures selon le RGPD). Organisez un exercice sur table une fois par an. Les équipes qui ont répété leur plan se rétablissent en quelques jours ; les autres improvisent pendant des semaines.
Tester : scanners, tests d'intrusion et contrôles continus
Chacun des contrôles ci-dessus peut être vérifié, et cette vérification doit être automatisée autant que possible pour ne pas se dégrader avec le temps. Voici une progression raisonnable, du gratuit et instantané au périodique et payant :
| Contrôle | Outil | Fréquence |
|---|---|---|
| Configuration TLS, chaîne, expiration | Vérification du Certificat SSL, SSL Labs, testssl.sh | Après chaque changement de certificat ou de serveur ; expiration tous les jours |
| En-têtes de sécurité et CSP | Vérification des En-têtes HTTP, MDN HTTP Observatory | Après chaque déploiement (intégrez-le à la CI) |
| Ports ouverts | Vérificateur de Ports, nmap | Après chaque modification du pare-feu ou du cloud |
| DNS, DNSSEC, authentification des e-mails | Vérificateur de Santé du Domaine, Vérificateur DMARC | Chaque mois, et après toute modification DNS |
| Sous-domaines obsolètes | Recherche de Sous-domaines | Chaque trimestre et à chaque démantèlement |
| Dépendances connues comme vulnérables | npm audit, Dependabot, Trivy | À chaque build |
| Failles au niveau du code (SAST) | Semgrep, CodeQL | À chaque pull request |
| Vulnérabilités web à l'exécution (DAST) | OWASP ZAP, Nuclei | Chaque semaine sur l'environnement de staging |
| Autorisation et logique métier | Test d'intrusion manuel ou programme de bug bounty | Chaque année, et après chaque fonctionnalité majeure |
Les scanners sont efficaces sur les injections, les en-têtes et les composants obsolètes, mais mauvais sur l'autorisation et la logique métier : prévoyez donc au moins un test humain par an pour tout ce qui manipule de l'argent ou des données personnelles. Corrigez selon l'exposition : tout ce qu'un utilisateur non authentifié peut exploiter depuis internet passe en premier.
La checklist de sécurité web
Copiez-la dans le README de votre projet ou dans votre outil de suivi de tickets. Chaque ligne reprend l'une des pratiques ci-dessus, formulée pour pouvoir être cochée ou non ; la dernière colonne en apporte la preuve.
| Couche | Pratique | Validé quand |
|---|---|---|
| Domaine | Registrar lock et MFA sur le compte registrar ; renouvellement automatique activé | Le WHOIS affiche clientTransferProhibited ; expiration à plus de 12 mois |
| DNS | Zone signée avec DNSSEC ; enregistrement CAA ne listant que vos AC | dig +dnssec renvoie RRSIG ; enregistrement DS présent dans la zone parente |
| DNS | Aucun enregistrement CNAME ou A orphelin | Chaque nom d'hôte trouvé par la Recherche de Sous-domaines pointe vers une ressource que vous contrôlez |
| TLS | TLS 1.2+ uniquement, TLS 1.3 de préférence, chaîne complète servie | Vérification du Certificat SSL : chaîne complète, TLS 1.0/1.1 refusés |
| TLS | HSTS avec un max-age d'un an, includeSubDomains, préchargé | Inscrit sur hstspreload.org |
| TLS | Renouvellement automatisé via ACME ; expiration surveillée | certbot renew --dry-run réussit ; alerte réglée à 14 jours |
| En-têtes | CSP (à base de nonce), frame-ancestors, nosniff, Referrer-Policy, Permissions-Policy | Note A à la Vérification des En-têtes HTTP |
| Authentification | Hachage Argon2id ou bcrypt ; règles de mot de passe NIST ; vérification dans une liste de fuites | Un hash prend de 100 à 250 ms ; aucune règle de composition |
| Authentification | MFA proposée à tous, obligatoire pour les administrateurs ; passkeys prises en charge | Connexion admin impossible sans second facteur |
| Authentification | Endpoints de connexion, de réinitialisation et de MFA limités par IP et par compte | La sixième tentative en une minute renvoie 429 |
| Sessions | Cookie __Host- avec Secure, HttpOnly, SameSite ; ID renouvelé à la connexion | Attributs du cookie visibles dans les DevTools ; ancienne session invalide après connexion |
| Entrées | Requêtes paramétrées partout ; sorties encodées selon le contexte ; uploads validés par leur contenu | Aucune requête construite par concaténation dans une recherche de code ; les payloads XSS s'affichent comme du texte |
| Contrôle d'accès | Routage avec refus par défaut ; contrôle de propriété par objet ; CORS strict | Rejouer les ID d'un autre utilisateur renvoie 404 ou 403 |
| Dépendances | Lockfile commité ; npm ci ; audit en CI ; actions épinglées par SHA ; SRI sur les scripts CDN | Le build échoue sur une CVE de gravité élevée |
| Serveur | Seuls 80 et 443 publics ; SSH par clé uniquement ; mises à jour de sécurité automatiques ; secrets en variables d'environnement ou dans un coffre-fort | Le Vérificateur de Ports montre 22, 3306 et 6379 fermés depuis internet |
| Sauvegardes | 3-2-1 avec une copie immuable ; restauration testée | Dernier test de restauration réussi datant de moins de 90 jours |
SPF -all, DKIM, DMARC p=reject, MTA-STS | Le Vérificateur DMARC valide ; rapports agrégés reçus | |
| Surveillance | Événements d'authentification et d'autorisation journalisés de façon centralisée ; alertes sur des schémas ; surveillance externe de la disponibilité, des certificats et du DNS | Alerte de test déclenchée et reçue |
| Réponse | Plan d'incident écrit ; security.txt publié ; exercice sur table réalisé | Plan revu au cours des 12 derniers mois |
Correspondance avec l'OWASP Top 10:2025
L'OWASP Top 10 est la liste de risques des applications web la plus citée, et son édition 2025 a remanié l'ordre et introduit deux nouvelles catégories. Si un client, un auditeur ou un référentiel de conformité vous demande comment vous y répondez, voici la correspondance avec les pratiques de ce guide :
| OWASP Top 10:2025 | Pratiques de ce guide |
|---|---|
| A01 Broken Access Control | Refus par défaut, contrôles par objet, CORS strict, verrouillage de l'administration |
| A02 Security Misconfiguration | En-têtes de sécurité, HSTS, ports fermés, en-têtes de version supprimés, listing des répertoires désactivé |
| A03 Software Supply Chain Failures (nouveau) | Lockfiles, audits, actions épinglées, SRI, SBOM, CI à privilèges minimaux |
| A04 Cryptographic Failures | TLS 1.2+ et 1.3, HSTS, Argon2id, gestion des secrets, sauvegardes chiffrées |
| A05 Injection | Requêtes paramétrées, encodage des sorties, CSP, validation des uploads |
| A06 Insecure Design | Modélisation des menaces par couche, comportement fail-closed par défaut, limitation de débit dès la conception |
| A07 Authentication Failures | Règles de mot de passe NIST, vérification des fuites, MFA et passkeys, rotation des sessions |
| A08 Software or Data Integrity Failures | SRI, dépendances signées et épinglées, désérialisation sûre |
| A09 Security Logging and Alerting Failures | Journalisation centralisée, alertes sur des schémas, surveillance externe |
| A10 Mishandling of Exceptional Conditions (nouveau) | Fail closed, réponses d'erreur uniformes, aucune stack trace montrée aux utilisateurs |
Vérifiez les en-têtes de sécurité de votre site en quelques secondes
Le vérificateur d'en-têtes HTTP gratuit de DNS Robot analyse n'importe quelle URL et note ses en-têtes de sécurité de A à F : HSTS, Content-Security-Policy, X-Frame-Options, X-Content-Type-Options, Referrer-Policy et Permissions-Policy, avec la valeur exacte trouvée et ce qui manque. Sans inscription.
Essayer le vérificateur d'en-têtes HTTPAdvertisement
FAQ sur la sécurité web
Imposez HTTPS avec un TLS moderne et HSTS, envoyez des en-têtes de sécurité stricts (en particulier une Content Security Policy), hachez les mots de passe avec Argon2id derrière la MFA et la limitation de débit, utilisez des requêtes paramétrées et l'encodage des sorties, appliquez le contrôle d'accès côté serveur pour chaque objet, gardez les dépendances à jour et épinglées, fermez les ports inutilisés et journalisez les événements de sécurité de façon centralisée. Verrouillez d'abord le domaine et le DNS, car tout le reste suppose que vous contrôliez toujours votre nom de domaine.