Web Application Security
Chapitre 1 / 9 · 12 min de lecture

Introduction à la sécurité des applications web

Pourquoi tout développeur doit comprendre les attaques pour mieux défendre : une brève histoire de la sécurité logicielle et le cadre Recon / Attaque / Défense.

Une application web moderne n'est plus un simple document HTML servi à un visiteur passif. C'est une application de bureau livrée dans un navigateur : elle stocke les données de ses utilisateurs, gère plusieurs niveaux de permissions, fait dialoguer une SPA et des API REST, et s'appuie sur des centaines de dépendances tierces réparties sur plusieurs serveurs. Cette richesse fonctionnelle a un revers : elle offre à un attaquant une surface d'attaque (attack surface) considérable. Chaque entrée utilisateur, chaque intégration, chaque bibliothèque importée est une porte potentielle.

Ce blog résume en profondeur l'ouvrage d'Andrew Hoffman, Web Application Security (O'Reilly, 2020). Sa thèse est simple et parfois déroutante pour qui débute : pour défendre efficacement une application, il faut comprendre comment raisonne et opère un attaquant. Ce premier chapitre pose le décor. Nous retraçons brièvement l'histoire de la sécurité logicielle — qui montre que défenses et attaques co-évoluent depuis un siècle —, nous présentons le cadre en trois temps du livre (Reconnaissance, Offense, Défense), et nous fixons fermement le cadre éthique et légal qui conditionne tout le reste. L'objectif final, ici comme dans chaque chapitre, reste défensif : écrire du code sûr et protéger ses propres applications.

Une brève histoire de la co-évolution attaque / défense

L'histoire du logiciel montre une constante : chaque mécanisme de défense suscite une parade, et chaque parade pousse à inventer une défense plus solide. Comprendre cette dynamique aide à adopter le bon état d'esprit — celui d'un défenseur qui anticipe.

De la machine Enigma au premier outil de cassage automatisé

Dans les années 1930, la machine Enigma chiffrait les communications militaires allemandes à l'aide d'un algorithme à clé symétrique (symmetric key algorithm) : une même configuration permettait de chiffrer et de déchiffrer. Sa faiblesse n'était pas mathématique mais opérationnelle : une seule configuration interceptée — l'équivalent d'une clé privée (private key) aujourd'hui — compromettait tout le réseau jusqu'au prochain changement, qui n'avait lieu qu'une fois par mois.

Le mathématicien polonais Marian Rejewski, puis l'équipe d'Alan Turing à Bletchley Park, ont rétro-conçu (reverse engineer) le système. Turing alla plus loin en construisant la Bombe, l'un des tout premiers outils de cassage automatisé : en exploitant un texte connu (les bulletins météo quotidiens), il appliqua ce qu'on nomme aujourd'hui une attaque à texte clair connu (known plaintext attack, KPA).

Note

La leçon défensive est durable. Hoffman souligne que le chiffrement symétrique reste utilisé aujourd'hui pour protéger les données en transit, mais avec deux améliorations majeures : des clés assez complexes pour résister des millions d'années au cassage par force brute (brute force attack), et surtout une rotation fréquente des clés (par session, par requête, ou à intervalle planifié). Une clé qui ne vit qu'une requête limite la casse à une seule requête.

Phreaking : concevoir pour le pire des cas

Dans les années 1950, le réseau téléphonique d'AT&T automatisa le routage des appels via la numérotation par tonalités (tone dialing). Des bricoleurs, les phreakers, découvrirent qu'en reproduisant certaines fréquences audio — notamment la tonalité de 2600 Hz, une véritable « commande d'administration » câblée dans le système — ils détournaient son fonctionnement. La riposte des années 1960, le DTMF (« Touch Tones »), utilisait deux fréquences simultanées, bien plus difficiles à imiter.

Le défaut originel du tone dialing porte un nom que tout développeur devrait retenir : la conception au mieux (best-case scenario design). Les architectes n'avaient envisagé que des utilisateurs honnêtes.

À retenir

La règle qui en découle traverse tout le livre : toujours concevoir en pensant au pire des cas d'abord. Un système déployé à grande échelle finira tôt ou tard face à un acteur malveillant. Le DTMF illustre l'idée inverse, positive : avec une planification appropriée, on peut rendre l'abus significativement plus coûteux.

Virus, vers, et le premier hacker condamné

Avec l'essor du PC dans les années 1980 apparaissent les hackers que nous reconnaissons aujourd'hui. En 1983, Fred Cohen écrit le premier virus informatique, capable de se copier et de se cacher dans un programme légitime — démontrant au passage qu'il est quasi impossible de distinguer algorithmiquement un virus d'un logiciel sain. En 1988, le ver de Morris (Morris Worm) infecte environ 15 000 machines en une journée et vaut à son auteur d'être le premier hacker condamné aux États-Unis.

Deux techniques de cette époque restent d'actualité, transposées au web : le passage à l'échelle (scalability) — sauter d'un utilisateur à l'autre — et le camouflage (camouflaging) — dissimuler du code malveillant dans un programme d'apparence légitime. C'est exactement ce que font aujourd'hui un hameçonnage (phishing) ou une extension de navigateur piégée.

Le Web 2.0 déplace la cible vers l'utilisateur

Dans les années 1990, le web n'était qu'une plateforme de partage de documents HTML. Le tournant des années 2000 — le Web 2.0 — change tout : les sites stockent les données soumises par les utilisateurs et adaptent leur comportement en fonction de ces entrées. Le web devient une plateforme de distribution d'applications, et avec lui naissent réseaux sociaux, blogs et wikis.

Ce basculement déplace la cible des attaquants. Serveurs et réseaux ayant été progressivement durcis, l'utilisateur devient la cible idéale. Les premières attaques par déni de service (DoS) médiatisées paralysent Yahoo!, Amazon et eBay ; le XSS (Cross-Site Scripting) prolifère, car les navigateurs n'avaient pas encore de défenses. La cause profonde : des technologies pensées pour un utilisateur unique (le propriétaire du site) s'effondrent dès qu'on les emploie pour faire partager des données entre de nombreux utilisateurs.

L'ère moderne : le navigateur durci, le code applicatif exposé

Les navigateurs actuels sont nettement plus sûrs. Ils isolent les sites d'origines différentes via la politique de même origine (Same Origin Policy, SOP), acceptent une politique de sécurité du contenu (Content Security Policy, CSP), et HTTP s'appuie désormais sur TLS (le successeur de SSL, aujourd'hui déprécié) pour chiffrer le trafic et rendre difficile une attaque de l'homme du milieu (man-in-the-middle attack).

Conséquence directe : les attaquants les plus efficaces ne s'en prennent plus au navigateur lui-même, mais à la logique écrite par les développeurs dans l'application. Or les applications modernes sont immenses — des centaines de dépendances open source, des intégrations multiples, plusieurs bases de données, plusieurs serveurs. C'est précisément cette logique métier, et cette surface d'attaque démultipliée, que ce blog vous apprend à défendre.

Piège courant

Cette histoire est cyclique. À mesure qu'une couche de la pile se durcit, les attaquants migrent vers une technologie émergente, moins bien protégée — peut-être demain les WebSockets ou la communication temps réel (RTC). Chaque nouvelle technologie apporte sa propre surface d'attaque. Ne considérez jamais la sécurité comme un état acquis une fois pour toutes : c'est un processus continu, à intégrer dans tout le cycle de vie logiciel.

L'état d'esprit du hacker, au service de la défense

Pourquoi un développeur soucieux de défense devrait-il étudier les attaques ? Parce que, comme l'écrit Hoffman, comprendre la mentalité d'un attaquant est souvent vital pour concevoir des bases de code sûres. On ne défend bien que ce dont on comprend les failles. Une défense de routine se contourne aisément ; une défense robuste exige de l'attaquant une compréhension profonde — et, du même coup, exige du défenseur cette même compréhension pour la construire.

Le livre s'organise donc en trois temps, dans un ordre pédagogique délibéré. Chacun éclaire les autres.

PhaseQuestion centraleFinalité défensive
Reconnaissance (Recon)Que peut-on apprendre de l'application sans l'attaquer ?Repérer ce que votre app expose involontairement et le masquer avant qu'un tiers ne le trouve.
Offense (Attaque)Comment une faille s'exploite-t-elle, mécaniquement ?Reconnaître dans votre propre code les schémas vulnérables.
DéfenseComment empêcher ou atténuer l'exploitation ?Le but ultime : écrire du code sûr et durcir l'architecture.

Reconnaissance : cartographier sans attaquer

La reconnaissance est la phase exploratoire de collecte d'informations qui précède en général toute tentative d'intrusion : on cherche à comprendre une application — techniquement et fonctionnellement — sans nécessairement chercher à la casser. Pour les meilleurs chasseurs de primes, c'est même la compétence qui distingue les « grands » des simples « bons ».

Côté défense, cette phase est précieuse : les informations qu'une application divulgue (endpoints cachés, structure de permissions, technologies utilisées) peuvent souvent être réduites par une planification appropriée. Hoffman illustre la notion de surface partielle avec l'exemple d'une banque : un client n'a qu'un accès essentiellement en lecture à son solde (au plus quelques écritures limitées comme un virement ou le paiement d'une facture), jamais le droit de créer ou supprimer un compte en ligne. Il existe donc, invisible pour lui, un ensemble d'applications à contrôle d'accès basé sur les rôles (role-based access control) réservées au personnel. Penser en termes de rôles et de privilèges, c'est déjà penser défense.

Offense : comprendre le mécanisme, pas fabriquer une arme

La phase d'offense analyse le code et les requêtes réseau pour exploiter des applications mal écrites ou mal configurées. Dans ce blog, conformément à notre cadre éducatif, nous expliquerons le mécanisme conceptuel de chaque faille — assez pour le reconnaître et le neutraliser dans votre code — sans jamais fournir d'exploit clé en main ni d'outillage réutilisable contre un système réel.

C'est ici qu'intervient la structure phare du livre, que ce blog reprend : pour chaque vulnérabilité, un exemple VULNÉRABLE est systématiquement suivi de sa version CORRIGÉE. L'exemple vulnérable n'a qu'une valeur illustrative ; la version corrigée est l'objectif.

// ❌ VULNÉRABLE : la saisie utilisateur est injectée
// directement dans le HTML (porte ouverte au XSS).
element.innerHTML = "Bonjour " + nomUtilisateur;

// ✅ CORRIGÉ : on traite la saisie comme du texte,
// jamais comme du markup exécutable.
element.textContent = "Bonjour " + nomUtilisateur;

Défense : la finalité de tout l'ouvrage

La troisième partie reprend chaque attaque vue précédemment, du point de vue exactement opposé : non plus pénétrer, mais prévenir ou atténuer. On y apprend des protections spécifiques à chaque faille, mais aussi des protections générales : méthodologies « sûres par défaut » (secure by default), bonnes pratiques de codage applicables par toute équipe via des tests et un simple analyseur statique (linter).

Attention

Toute mesure de sécurité a un compromis (trade-off) hors sécurité : souvent une baisse de performance (lire et assainir des données coûte des opérations supplémentaires), parfois un surcoût de maintenance, parfois une utilisabilité réduite. L'exemple canonique est le message d'erreur de connexion : un message précis (« mot de passe incorrect ») confirme à l'attaquant qu'un identifiant existe et facilite le cassage par force brute. Un message générique protège mieux, au prix d'une expérience utilisateur un peu dégradée. Connaître ces arbitrages fait partie du métier.

Les grands principes défensifs récurrents

Au fil des chapitres, quelques principes reviennent constamment. Les garder à l'esprit dès la conception vaut mieux que de colmater après coup.

  • Ne jamais faire confiance aux entrées (never trust user input). Toute donnée venant du client — formulaire, paramètre d'URL, en-tête HTTP, fichier téléversé — est potentiellement hostile. Elle doit être validée, et assainie ou échappée selon le contexte où elle sera utilisée (HTML, SQL, shell…).
  • Moindre privilège (least privilege). Chaque utilisateur, chaque service, chaque composant ne reçoit que les permissions strictement nécessaires. Le client d'une banque a un accès en lecture seule ; votre code applicatif ne devrait pas tourner avec un compte de base de données administrateur.
  • Défense en profondeur (defense in depth). On superpose plusieurs barrières indépendantes (validation côté serveur et CSP et requêtes paramétrées…) de sorte que la défaillance d'une couche n'expose pas tout le système.
  • Sûr par défaut (secure by default). La configuration par défaut, et le chemin de moindre effort pour un développeur, doivent être les plus sûrs — pas les plus permissifs.
  • Concevoir pour le pire cas. Hériter de la leçon du phreaking : envisager d'emblée l'utilisateur malveillant, jamais seulement l'utilisateur idéal.

Panorama des failles couvertes

Le blog suivra l'organisation faille par faille du livre. Voici les grandes familles que nous explorerons — toujours selon le schéma « comment ça marche » (bref, conceptuel) puis « comment se défendre » (développé).

FailleMécanisme en une phraseDirection de la défense
XSS (Cross-Site Scripting)Forcer le navigateur d'un autre utilisateur à exécuter du code de l'attaquant.Échapper les sorties selon le contexte, CSP, ne pas injecter de markup brut.
CSRF (Cross-Site Request Forgery)Détourner les permissions d'un utilisateur authentifié pour émettre des requêtes à son insu.Jeton anti-CSRF (CSRF token), attribut SameSite sur les cookies.
XXE (XML External Entity)Abuser d'un parseur XML mal configuré pour lire des fichiers locaux ou inclure des ressources distantes.Désactiver les entités externes du parseur.
Injections (SQL, commandes…)Mêler données et instructions pour faire exécuter au système des ordres non prévus.Requêtes paramétrées (parameterized queries), validation stricte.
DoS / DDoSSaturer serveur ou client de requêtes pour dégrader ou rompre le service.Limitation de débit (rate limiting), quotas, code sans complexité explosive.
Dépendances tiercesImporter du code open source vulnérable ou malveillant.Inventaire, mises à jour, audit des dépendances.

Cadre éthique et légal : impératif

Ces connaissances ont un seul usage légitime dans ce blog : protéger vos propres applications et celles que vous êtes autorisé à tester. Hoffman insiste : tester les techniques décrites uniquement contre une application que vous possédez ou pour laquelle vous disposez d'une permission écrite explicite.

Piège courant

Même de simples techniques de reconnaissance peuvent faire signaler votre adresse IP, entraîner un bannissement, voire des poursuites judiciaires. Une mauvaise utilisation des techniques offensives peut, selon la législation de votre pays, conduire à des amendes ou à de la prison. N'attaquez jamais un système tiers sans autorisation.

Les cadres légitimes existent et sont encouragés : le test d'intrusion (pen test) mandaté, et les programmes de prime aux bogues (bug bounty) assortis d'une divulgation responsable (responsible disclosure), où une entreprise autorise et récompense la recherche de failles dans ses produits. C'est la voie pour aiguiser ses compétences tout en aidant les autres à se sécuriser — jamais à leurs dépens.

À retenir

  • Les applications web modernes (SPA, API REST, multitude de dépendances) ont une surface d'attaque énorme : chaque entrée et chaque intégration est une porte à défendre.
  • L'histoire de la sécurité, d'Enigma au Web 2.0, montre une co-évolution permanente de l'attaque et de la défense : la sécurité est un processus, jamais un état acquis.
  • Comprendre l'attaquant pour mieux défendre : le livre s'articule en Reconnaissance → Offense → Défense, cette dernière étant la finalité de tout l'ouvrage.
  • Cinq principes guident la défense : ne jamais faire confiance aux entrées, moindre privilège, défense en profondeur, sûr par défaut, concevoir pour le pire cas.
  • Chaque faille (XSS, CSRF, XXE, injections, DoS, dépendances) sera traitée « mécanisme bref, puis défense développée », avec des exemples vulnérable → corrigé.
  • Cadre éthique et légal impératif : ces savoirs servent à protéger vos applications et à mener des tests autorisés (pen test, bug bounty avec permission) — jamais à attaquer des systèmes tiers.