Le top 10 des vulnérabilités de l’OWASP est le point de départ idéal pour les développeurs web qui souhaitent améliorer leurs compétences en sécurité.
Découvrons comment ces vulnérabilités prennent forme dans les applications web fullstack, avec Next.js et d’autres frameworks, et comment les éliminer.
Cet article est une traduction de l’article d’Eric Burel publié sur Smashing Magazine, “How OWASP Helps You Secure Your Full-Stack Web Applications”.
Vous préférez les vidéos ? Découvrez le replay du talk “Securing Server-Rendered Applications – Next.js Case” sur le site de GitNation.
La sécurité est un sujet intimidant pour les développeurs web. Le vocabulaire est riche et plein d’acronymes. Les tendances évoluent rapidement alors que les hackers et les analystes jouent perpétuellement au chat et à la souris.
Les vulnérabilités découlent de petits détails sur lesquels nous ne pouvons pas nous permettre de passer trop de temps au quotidien.
Les développeurs JavaScript ont déjà beaucoup à faire avec l’émergence d’une nouvelle vague d’architectures innovantes, telles que les React Server Components, l’App Router de Next.js ou les îlots d’Astro, même lorsqu’ils ont suivi nos formations à Next.js et à Astro.js !.
Ce dont nous avons besoin pour rester efficaces, c’est d’être en mesure de détecter et de pallier les problèmes de sécurité les plus courants. Un top dix des vulnérabilités les plus courantes serait idéal.
Bonne nouvelle : il existe justement un tel top dix des vulnérabilités les plus courantes, créé par des experts du domaine !
Le top 10 de l’OWASP est proposé par la Fondation OWASP et c’est une ressource extrêmement précieuse pour se lancer dans le domaine de la sécurité.
OWASP signifie “Open Worldwide Application Security Project”. Il s’agit d’une fondation à but non lucratif dont l’objectif est de rendre les logiciels plus sûrs à l’échelle mondiale. Elle soutient de nombreux projets open source et produit des ressources éducatives de haute qualité, notamment une liste des 10 principales vulnérabilités affectant les applications web.
Dans cet article, nous allons plonger dans chaque point du top 10 de l’OWASP pour comprendre comment reconnaître ces vulnérabilités dans une application fullstack.
Cet article est long, c’est le moment de vous préparer un thé ou un café :) ☕
Nous utiliserons Next.js comme exemple, mais ces connaissances s’appliquent à toute architecture fullstack similaire, même en dehors de l’écosystème JavaScript.
Commençons notre compte à rebours vers un web plus sûr !
En français : “falsification de requête côté serveur”, un nom charmant…
Vous avez peut-être entendu parler du Server-Side Rendering, alias SSR ? Eh bien, vous pouvez considérer le SSRF comme son acronyme jumeau maléfique.
Une vulnérabilité SSRF peut se résumer à laisser un attaquant lancer des requêtes en utilisant votre serveur backend.
Outre les coûts d’hébergement qui peuvent augmenter, le principal problème est que l’attaquant bénéficiera du niveau d’accréditation de votre serveur. Dans une architecture complexe, cela signifie pouvoir cibler vos services internes privés, en utilisant votre propre serveur corrompu.
Voici un exemple. Notre application permet à un utilisateur de saisir une URL et de résumer le contenu de la page cible côté serveur en utilisant un SDK d’IA. Un utilisateur malveillant passe “localhost
” comme URL, au lieu d’un site web qu’il souhaite résumer. Votre serveur lancera une requête contre lui-même ou tout autre service fonctionnant sur le port 3000 dans votre infrastructure backend. Il s’agit d’une vulnérabilité SSRF sévère !Vous devrez être vigilant lorsque vous déclenchez des requêtes basées sur les inputs des utilisateurs, en particulier côté serveur.
En français : “échec dans le logging et le monitoring de sécurité”.
Établir une connexion télépathique avec notre serveur Node.js qui tourne en backend serait incroyable. Au lieu de cela, la meilleure chose dont nous disposons pour voir ce qu’il se passe dans le cloud est un flux infini de morceaux de texte non structurés, que nous appelons affectueusement (ou pas) des “logs”.
Pourtant, nous devons composer avec cela, non seulement pour le debugging ou l’optimisation des performances, mais aussi parce que les logs sont souvent les seules informations dont nous disposons pour découvrir et remédier à un problème de sécurité.
Pour commencer, vous pouvez vous concentrer sur le logging des transactions les plus importantes de votre application. Exactement comme vous prioriseriez l’écriture de tests end-to-end. Dans la plupart des applications, cela signifie login, signup, paiements, envoi de mails… Dans une plus grande entreprise, une solution de télémétrie plus complète est indispensable, par exemple Open Telemetry, Sentry ou Datadog.
Si vous utilisez les React Server Components, envisagez la mise en place une stratégie de logging appropriée, car il n’est pas possible de les debugger directement depuis le navigateur comme nous avions l’habitude de le faire pour les composants client.
En français : “échec à préserver l’intégrité des logiciels et des données”.
Le top 10 des vulnérabilités de l’OWASP tend à avoir différents niveaux de granularité, et celle-ci est vraiment une grande famille. Concentrons-nous sur les attaques ciblant chaîne logistique (supply chain), car elles ont gagné en popularité au fil des années.
Vous avez peut-être entendu parler de la vulnérabilité Log4J. Elle a été très médiatisée, car c’est une énorme attaque s’appuyant sur la supply chain.
Dans l’écosystème JavaScript, vous installez très probablement vos dépendances en utilisant NPM. Avant de choisir des dépendances, vous pouvez établir une petite liste d’indicateurs. La librairie est-elle maintenue, testée avec du code propre ? Joue-t-elle un rôle critique dans l’application ? Qui est le principal contributeur ? Ai-je bien orthographié son nom lors de l’installation ?
Pour les applications plus sensibles, vous pouvez envisager de mettre en place une solution de SCA, Dependabot de GitHub en est une gratuite, Snyk et Datadog sont d’autres acteurs du domaine.
En français : “échec d’identification et d’authentification”.
Votre mot de passe administrateur fuite. Un hacker le trouve, boum, game over.
La gestion des mots de passe dépasse le cadre de cet article. Mais dans le contexte du développement web fullstack, on peut évoquer parades aux attaques par force brute, via les middlewares edge de Next.js.
Les middlewares sont de minuscules serveurs proxy écrits en JavaScript. Ils traitent les requêtes d’une manière qui est censée être très très rapide, plus rapide qu’un programme Node.js normal. Ils conviennent bien pour gérer des traitements de bas niveau, comme le blocage d’IP malveillantes ou la redirection des utilisateurs vers la bonne traduction d’une page.
Un cas d’utilisation intéressant est le rate limiting. Vous pouvez améliorer la sécurité de vos applications en limitant la capacité des attaquants à spammer vos points d’entrée “POST”, en particulier ceux dédiés à l’authentification.
Vous pouvez aller encore plus loin en mettant en place un pare-feu d’applications web (Web Application Firewall ou WAF). Un WAF permet aux développeurs de mettre en œuvre des règles de sécurité élaborées. Ce n’est pas quelque chose qui se configure au sein de votre application, mais plutôt au niveau de l’hébergement. Par exemple, Vercel a publié son propre WAF en 2024.
En français : “composants vulnérables et obsolètes”.
Nous avons déjà discuté des attaques ciblant la supply chain. Les composants obsolètes sont une variante de cette vulnérabilité, où c’est en fait vous qui êtes à blâmer. Désolé.
Votre application dépend de nombreux packages. Malheureusement, certains d’entre eux sont probablement affectés par des vulnérabilités qui peuvent se propager à votre application.
Les failles de sécurité sont souvent découvertes à l’avance par des analystes en sécurité diligents, avant même qu’un attaquant malveillant ne puisse commencer à les exploiter. Merci les analystes ! Lorsque cela se produit, ils remplissent une “Common Vulnerabilities and Exposure (CVE)"" et la stockent dans une base de données publique.
Le remède à cette vulnérabilité est le même que pour les attaques de la chaîne logistique au sens large : mettez en place une solution SCA comme Dependabot qui vérifiera régulièrement l’utilisation de packages vulnérables dans votre application.
Votre application dépend probablement de librairies et modules divers : leurs vulnérabilités peuvent se transmettre à votre application.
Nous avons beaucoup progressé depuis le début de cet article !
En résumé :
Nous savons comment reconnaître une SSRF. C’est une vulnérabilité sévère, facile à introduire accidentellement lors de la création d’une nouvelle fonctionnalité.
Nous avons identifié les solutions de monitoring et d’analyse des dépendances comme des éléments importants pour sécuriser les applications.
Nous avons trouvé un bon cas d’utilisation pour les middlewares edge de Next.js : mettre en oeuvre le rate limiting sur nos points d’entrée d’API pour l’authentification, afin d’empêcher les attaques par force brute.
C’est le bon moment pour aller prendre un deuxième thé ou café. Mais après ça, revenez avec nous car nous allons découvrir les cinq vulnérabilités les plus courantes affectant les applications web !
En français : “mauvaise configuration de sécurité”.
Il y a tellement de configurations que nous pouvons mal gérer… Mais concentrons-nous sur les plus pertinentes pour un développeur web qui apprend la sécurité : les en-têtes HTTP.
Vous pouvez utiliser les en-têtes de réponse HTTP pour transmettre beaucoup d’informations au navigateur de l’utilisateur. Ces informations indiquent notamment sur ce qui est possible ou non sur votre site web.
Par exemple, avec l’en-tête “Permissions-Policy”, vous pouvez affirmer que votre site web ne nécessitera jamais l’accès à la caméra de l’utilisateur. C’est un mécanisme de protection extrêmement puissant en cas d’attaque par injection de script (XSS). Même si le hacker parvient à exécuter un script malveillant dans le navigateur de la victime, le navigateur ne permettra pas au script d’accéder à la caméra.
Observez la configuration de sécurité des templates ou boilerplates que vous avez utilisé pour créer vos propres sites web. Les comprenez-vous correctement ? Pouvez-vous les améliorer ? Répondre à ces questions vous mènera inévitablement à augmenter considérablement la sécurité de vos sites web !
En français : “design non sécurisé”.
Le mauvais code est littéralement la 4ème cause de vulnérabilité dans les applications web ! En tant que développeurs, vous ne pouvez plus simplement critiquer votre équipe d’infrastructure : vous êtes aussi un peu coupable 😮.
Le design n’est pas seulement une question de code. Il s’agit plus généralement de la manière dont nous utilisons nos outils pour produire des applications.
Un mauvais design peut créer des vulnérabilités très difficiles à détecter. Le remède est un bon design, et un bon design nécessite beaucoup d’apprentissage. Continuez à lire nos articles sur Next.js et Astro.js et tout ira bien !
Dans le contexte des frameworks JavaScript full-stack, nous vous recommandons d’apprendre à les utiliser de manière idiomatique, comme pour une langue étrangère. Il ne s’agit pas seulement de traduire ce que vous savez déjà mot à mot. Vous devez comprendre comment un locuteur natif formulerait ses pensées.
Apprendre Next.js de manière idiomatique est vraiment très difficile. Ce n’est pas pour rien que nous formons les développeurs à cette technologie avec des programmes complets sur plusieurs jours. Next est centré sur l’hybridation de la logique client et serveur, et certains patterns peuvent ne pas se transférer à des frameworks concurrents avec une architecture différente, comme Astro.js ou Remix.
Heureusement, l’équipe de développement de Next.js a produit de nombreuses ressources d’apprentissage gratuites, y compris des articles et une documentation se concentrant spécifiquement sur la sécurité.
Le célèbre article de Sebastian Markbåge “How to Think About Security in Next.js” (lien en bas de page) est un bon point de départ. Si vous utilisez Next.js dans un contexte professionnel, pensez à organiser des sessions de formation avant de commencer à travailler sur des projets à forts enjeux.
En français : “une bonne vieille injection à l’ancienne comme on les aime”.
Les injections sont la quintessence des failles, le parangon des problèmes de sécurité. Les injections SQL sont très connues mais les injections JavaScript sont également courantes. Malgré leur notoriété, les injections sont toujours dans le top 3 du classement OWASP, il est difficile de les éliminer !
Les injections sont la raison pour laquelle forcer un composant React à rendre du HTML se fait via une prop "dangerouslySetInnerHTML"
. React ne veut pas que vous y incluiez un input utilisateur qui pourrait contenir un script malveillant.
La capture d’écran ci-dessous est une démonstration d’une injection utilisant des images. Elle pourrait cibler un forum de discussion par exemple. L’attaquant a exploité le système de publication d’images, en passant une URL qui pointe vers un endpoint d’API GET au lieu d’une véritable image. Chaque fois que les utilisateurs de votre site web voient ce post dans leur navigateur, une requête authentifiée est lancée contre votre backend, déclenchant un paiement !
En bonus, avoir un endpoint GET qui déclenche des effets de bord (side effects) comme un paiement constitue également un risque de Cross-Site Request Forgery (CSRF, qui est le cousin côté client des SSRF).
Cette image déclenche des paiements en utilisant l’identité de l’utilisateur final lorsqu’elle est affichée. L’erreur réside dans l’utilisation d’un endpoint GET pour déclencher des paiements, au lieu d’un endpoint POST.
Même les développeurs expérimentés peuvent être pris au dépourvu. Saviez-vous que dans Next.js ou Astro.js les paramètres de route dynamiques sont des entrées utilisateur ? Par exemple [language]/page.jsx
dans une app Next.js ou Astro. Nous observons souvent des tentatives d’attaque maladroites dans les logs : [language]
remplacé par une traversée de chemin du type "../../../../passwords.txt"
.
Zod est une librairie très populaire pour exécuter la validation des entrées des utilisateurs, côté serveur et côté client. Vous pouvez ajouter une étape de transformation pour assainir les entrées incluses dans les requêtes de base de données ou qui pourraient atterrir dans des endroits où elles finissent par être exécutées en tant que code.
En français : “échec de cryptographie”.
Voici une discussion typique entre deux développeurs qui ont un gros, gros problème :
- "Nous avons perdu notre base de données et notre clé de chiffrement.
Quel était l'algorithme utilisé pour chiffrer les mots de passe déjà ?
AES-128 ou SHA-512 ?"
- "Je ne sais pas, c'est la même chose non ?
Ils transforment les mots de passe en charabia ?"
- "D'accord. On a un gros, gros problème."
Cette vulnérabilité concerne principalement les développeurs backend qui doivent gérer des identifiants personnels sensibles (PII) ou des mots de passe.
Vous avez besoin d’algorithmes non réversibles pour chiffrer les mots de passe, c’est-à-dire des algorithmes de hachage.
L’idée est que si les mots de passe chiffrés sont volés, et que la clé de chiffrement est également volée, il sera toujours très difficile de pirater un compte (vous ne pouvez pas simplement inverser le chiffrement). On ne peut pas empêcher toutes les attaques, il faut donc aussi penser à atténuer la gravité des pires scénarios.
Dans le sondage State of JavaScript, nous utilisons une authentification sans mot de passe avec un lien magique par e-mail, et un hachage à sens unique des e-mails. Donc même en tant qu’administrateurs, nous ne pouvons pas deviner l’e-mail d’un utilisateur dans notre base de données.
Un hachage d’email généré lorsqu’un utilisateur crée un compte : il ne peut pas être inversé même en possédant la clé de chiffrement.
Nous arrivons à la dernière vulnérabilité de notre liste. Quel suspense, nous sommes sur le point de découvrir que la vulnérabilité numéro 1 dans le monde du développement web est…
En français : “contrôle d’accès cassé de chez cassé”.
Le nom n’est pas très intuitif, alors voici une refomulation. Il s’agit d’une situation ou des personnes peuvent accéder aux comptes d’autres personnes, ou à des ressources auxquelles elles ne sont pas autorisées à accéder. C’est plus impressionnant quand on le dit comme ça.
Il y a quelque temps, nous avons démontré que vérifier les autorisations dans un layout Next.js peut faire fuiter des pages privées. Ce n’est pas un défaut de conception de Next.js, mais la conséquence d’une différence de fonctionnement entre les React Server Components et les Client Components.
Voici une démo de la façon dont vous pouvez implémenter un paywall dans Next.js qui ne protège rien.
// app/layout.jsx
// Vérification du cookie de connexion
// pour accéder aux contenus payants du site
async function checkPaid() {
const token = cookies.get("auth_token");
return await db.hasPayments(token);
}
// Vérification du paiement dans un layout
// pour l'appliquer à toutes les pages
// ❌ Malheureusement, ce n'est pas comme ça que fonctionne Next.js !
export default async function Layout() {
const hasPaid = await checkPaid();
if (!hasPaid) redirect("/subscribe");
// rendu de la page sous-jacente
return <div>{children}</div>;
}
// ❌ on peut contourner le layout et obtenir la page
// en ajoutant "RSC=1" aux en-têtes de la requête !
export default function Page() {
return <div>CONTENU PAYANT</div>
}
La plupart des vulnérabilités courantes sont étroitement liées à des problèmes de conception :
Ces vulnérabilités sont redoutables car elles nous confrontent à nos propres limites en tant que développeurs web. Personne n’est parfait et même les développeurs les plus expérimentés écriront inévitablement du code vulnérable à un moment donné, sans même s’en rendre compte.
Comment l’éviter ? En ne restant pas seul ! En cas de doute, demandez à d’autres développeurs, il y a de grandes chances que quelqu’un ait été confronté aux mêmes problèmes que vous et puisse vous proposer des solutions.
Tout d’abord, en lisant cet article, vous avez déjà fait un excellent travail pour améliorer la sécurité de vos applications. Félicitations !
La plupart des hackers adoptent une stratégie de volume et ne sont pas particulièrement compétents. Ils sont donc en difficulté face à des développeurs éduqués qui peuvent repérer et corriger les vulnérabilités les plus courantes.
En découvrant comment le top 10 OWASP peut affecter les applications JavaScript fullstack, vous venez de rendre la vie des hackers beaucoup plus difficile !
À partir de là, nous pouvons vous suggérer quelques pistes pour devenir encore meilleur dans la sécurisation de vos applications web :
Vous trouverez de nombreuses ressources additionnelles à la fin de l’article, vous aurez donc de quoi lire !
Merci de votre lecture et codez prudemment !
Version originale de cet article sur Smashing Magazine : https://www.smashingmagazine.com/2025/02/how-owasp-helps-secure-full-stack-web-applications/
Une démo interactive d’un SSRF dans une app Next.js et comment le corriger https://nextpatterns.dev/p/security/ssrf-server-action
OWASP Top 10 : https://owasp.org/www-project-top-ten/
Une vulnérabilité SSRF qui a affecté le système d’optimisation d’images de Next.js : https://www.assetnote.io/resources/research/digging-for-ssrf-in-nextjs-apps
Observer les React Server Components en utilisant Open Telemetry : https://www.dash0.com/blog/how-to-inspect-react-server-component-activity-with-next-js
OpenTelemetry, un standard open source pour la télémétrie : https://opentelemetry.io/
À propos de la vulnérabilité Log4J : https://www.ibm.com/think/topics/log4j
Mettre en place une limitation de débit (rate limiting) dans un middleware en utilisant un service Redis : https://upstash.com/blog/edge-rate-limiting
Annonce du WAF de Vercel : https://vercel.com/blog/introducing-the-vercel-waf
Base de données Mitre CV : https://cve.mitre.org/
Une démo interactive d’une vulnérabilité CSRF dans une app Next.js, et comment la corriger : https://nextpatterns.dev/p/security/csrf-image
Un guide super complet sur l’authentification ciblant spécifiquement les applications web : https://www.smashingmagazine.com/2023/01/authentication-websites-banking-analogy/
Validation de formulaire côté serveur avec zod dans Next.js (Astro l’a de façon native) : https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations#server-side-form-validation
“Sanitisation” avec zod : https://github.com/colinhacks/zod/discussions/1358
Sécuriser du contenu payant rendu statiquement dans Next.js, et pourquoi les layouts sont un mauvais endroit pour faire des vérifications d’authentification : https://www.ericburel.tech/blog/static-paid-content-app-router
Articles de Smashing Magazine liés à la sécurité (près de 50 résultats au moment où nous écrivons ces lignes !) : https://www.smashingmagazine.com/search/?q=security
Talk d’Eric Burel pour React Advanced London 2024 “Sécuriser les applications Server-Rendered : le cas Next.js”. Vous pouvez voir la rediffusion en ligne : https://gitnation.com/contents/securing-server-rendered-applications-nextjs-case
Vous avez apprécié cette ressource ?
Découvrez toutes nos formations Next.js, Astro.js et LangChain en présentiel ou en distanciel