En une phrase
La Subresource Integrity (SRI) est une fonctionnalité de sécurité qui permet aux navigateurs de vérifier que les fichiers qu'ils récupèrent depuis des sources externes, comme les CDN, n'ont pas été modifiés en secret.
Le problème que ça résout
Imaginez : vous êtes en train de développer une nouvelle web app super classe. Pour qu'elle soit bien rapide, vous utilisez un Content Delivery Network (CDN) pour servir des bibliothèques courantes comme React, Vue, ou même juste quelques polices de caractères un peu fancy. C'est une pratique standard. Vos utilisateurs bénéficient d'une expérience plus rapide parce que le fichier est probablement déjà dans le cache de leur navigateur après avoir visité un autre site, ou parce qu'il est servi depuis un serveur physiquement plus proche d'eux. Gagnant-gagnant, non ?
Presque. Sauf que vous venez d'introduire un énorme facteur de confiance. Vous faites confiance au fournisseur de CDN pour qu'il serve toujours le fichier exact que vous aviez prévu. Et si ce CDN se faisait pirater ? Un attaquant pourrait remplacer le gentil et serviable react.min.js par une version malveillante : react.min.js-plus-un-crypto-mineur-et-voleur-de-mots-de-passe.
Soudain, ce code malveillant s'exécute sur votre site web, avec l'entière confiance des navigateurs de vos utilisateurs. Il peut siphonner les identifiants de connexion, défigurer vos pages ou enrôler vos visiteurs dans un botnet. C'est une attaque de la chaîne d'approvisionnement (supply-chain) classique, et c'est terrifiant parce que vous n'avez rien fait de mal sur votre propre serveur. Vous avez juste fait confiance à la mauvaise personne au mauvais moment.
Avant la SRI, il n'y avait aucun mécanisme natif dans les navigateurs pour se défendre contre ça. Les développeurs utilisaient des solutions de contournement, mais elles étaient bancales. La SRI a été créée par le W3C pour résoudre ce problème spécifique de front. Elle fournit un moyen simple et standardisé de dire au navigateur : « Hé, va chercher ce script, mais avant de l'exécuter, assure-toi absolument que c'est bien celui que j'attends. S'il y a ne serait-ce qu'un seul octet de différence, balance-le et préviens-moi. »
Comment ça marche sous le capot
La SRI est un mariage astucieux entre un simple attribut HTML et de solides principes de cryptographie. Décortiquons tout ça.
L'attribut integrity
La magie commence avec un nouvel attribut que vous pouvez ajouter à vos balises <script> et <link>. Il s'appelle, judicieusement, integrity.
<script
src="https://code.jquery.com/jquery-3.6.0.min.js"
integrity="sha384-oBqDVmMz9ATKxIep9tiCxS/Z9fNfEXiDAYTujMAeBAsjFuCZSmKbSSUnQlmh/jp3"
crossorigin="anonymous"></script>
Cet attribut contient une chaîne de caractères avec deux parties : un préfixe d'algorithme de hash (ici, sha384-) et un hash cryptographique encodé en Base64. C'est « l'empreinte numérique » du fichier que vous vous attendez à recevoir.
Le Hash : une empreinte numérique
Une fonction de hashage cryptographique est un algorithme mathématique qui prend une entrée (comme le contenu entier d'un fichier JavaScript) et produit une chaîne de caractères courte et de taille fixe, appelée un hash. Pensez-y comme à un checksum sous stéroïdes.
Ces hashs ont quelques propriétés cruciales :
- Déterministes : Le même fichier d'entrée produira toujours exactement le même hash.
- Effet d'avalanche : Changez un seul caractère dans le fichier d'entrée — ajoutez un espace, modifiez un nom de variable — et le hash résultant sera complètement différent et méconnaissable.
- À sens unique : Il est pratiquement impossible d'inverser le processus. Vous ne pouvez pas prendre le hash et deviner quel était le contenu original du fichier.
Le standard SRI prend en charge trois algorithmes de hash sécurisés : SHA-256, SHA-384 et SHA-512. Le nombre fait référence à la longueur en bits du hash, et plus c'est grand, plus c'est fort. SHA-384 est un excellent choix polyvalent.
Donc, lorsque vous vous apprêtez à lier un fichier depuis un CDN, vous générez d'abord son hash. Vous prenez essentiellement un instantané du fichier à ce moment-là et vous dites au navigateur : « Voilà à quoi ressemble le vrai jquery-3.6.0.min.js. »
L'attribut crossorigin
Vous voyez ce crossorigin="anonymous" dans l'exemple ? Ce n'est pas juste pour faire joli ; c'est obligatoire. Pour qu'un navigateur récupère une ressource d'une origine différente (par exemple, votre site mon-app.com qui récupère un script sur code.jquery.com) et inspecte son contenu pour la vérification SRI, il a besoin d'une permission via le Cross-Origin Resource Sharing (CORS).
Définir crossorigin="anonymous" indique au navigateur de faire la requête sans envoyer d'informations d'identification de l'utilisateur comme des cookies ou des en-têtes d'authentification HTTP. C'est un must en matière de sécurité et de confidentialité. Si vous oubliez cet attribut, le navigateur refusera d'effectuer la vérification d'intégrité et bloquera simplement le chargement de la ressource, ce qui cassera votre site.
En résumé : la checklist du navigateur
Lorsqu'un navigateur rencontre une balise avec un attribut integrity, il suit ce protocole strict :
- Il voit la balise
<script>et note les attributssrc,integrityetcrossorigin. - Il envoie une requête pour le fichier à l'URL
src. Grâce àcrossorigin, c'est une requête CORS. - Le fichier est téléchargé.
- Point crucial, avant d'exécuter quoi que ce soit, le navigateur calcule son propre hash du contenu du fichier téléchargé, en utilisant le même algorithme spécifié dans l'attribut
integrity(par exemple,sha384). - Il compare ensuite le hash qu'il vient de calculer avec celui que vous avez fourni dans l'attribut.
- S'ils correspondent : Hourra ! Le fichier est authentique. Le navigateur exécute le script ou applique la feuille de style.
- S'ils ne correspondent pas : ALERTE ROUGE ! Le navigateur suppose que le fichier a été altéré. Il ignore complètement le fichier et ne l'exécute pas. Il envoie alors une erreur
Failed to find a valid digestdans la console du développeur. Votre site pourrait sembler cassé (par exemple, un graphique ou une police manquante), mais vous avez brillamment évité une catastrophe.
Histoires vécues
Le tableau de bord d'analytique défiguré
Une équipe marketing utilisait un tableau de bord qui s'appuyait sur une bibliothèque de graphiques tierce, récupérée depuis un CDN de niche, pour visualiser les données de leurs campagnes. Le développeur, qui venait de se renseigner sur les bonnes pratiques de sécurité, avait ajouté des hashs SRI à la balise <script> de la bibliothèque. Un lundi matin, le CDN a été brièvement compromis. Un attaquant a remplacé la populaire bibliothèque de graphiques par un script qui affichait juste un visage géant et moqueur en art ASCII.
Lorsque l'équipe marketing a chargé son tableau de bord, les graphiques étaient cassés. Ils voyaient des boîtes vides. Ils ont appelé le service informatique, agacés. Le développeur a vérifié la console du navigateur et a vu la magnifique erreur de validation SRI. Le navigateur avait détecté le fichier modifié, avait refusé de l'exécuter et avait empêché la défiguration. Au lieu d'un incident de sécurité majeur avec des directeurs en panique, ça s'est réglé par une enquête de 15 minutes qui s'est terminée en pointant temporairement vers un autre CDN.
Leçon : SRI transforme une catastrophe de sécurité potentielle en un simple problème de disponibilité maîtrisable.
Le crypto-mineur sournois
Une bibliothèque utilitaire JavaScript populaire et légère, hébergée sur un CDN gratuit, était très appréciée des développeurs indépendants. Un attaquant a obtenu l'accès au CDN et a modifié le fichier de la bibliothèque, ajoutant quelques lignes de code obfusquées qui lançaient un crypto-mineur en WebAssembly. La taille du fichier a à peine changé, et les fonctions principales de la bibliothèque fonctionnaient toujours parfaitement.
Les sites web utilisant la bibliothèque sans SRI ont soudainement vu les ventilateurs des portables de leurs utilisateurs s'emballer et leurs batteries se vider. Les utilisateurs se plaignaient de lenteurs, mais c'était difficile à diagnostiquer. Les sites eux-mêmes semblaient normaux. Cependant, les sites qui avaient implémenté la SRI étaient immunisés. Leurs navigateurs bloquaient le script modifié, et bien que les fonctions utilitaires soient cassées, les processeurs de leurs utilisateurs étaient en sécurité.
Leçon : SRI n'attrape pas seulement les défigurations évidentes, mais aussi les attaques subtiles et parasitaires qui peuvent nuire à la réputation de votre site.
La mise à jour de police oubliée
Un designer insistait pour utiliser une version spécifique d'une police de caractères provenant d'une fonderie tierce, servie via leur CDN. Le développeur a consciencieusement copié la balise <link>, avec son hash SRI. Le site a été lancé et était superbe. Six mois plus tard, la fonderie a mis à jour le fichier de la police pour ajouter de nouveaux symboles monétaires et améliorer le crénage. C'était une mise à jour légitime et utile.
Soudainement, le texte du site est revenu à un moche Arial par défaut. Le développeur était perplexe jusqu'à ce qu'il vérifie la console et voie l'erreur SRI. Le navigateur bloquait correctement le nouveau fichier de police modifié car son hash ne correspondait plus à l'ancien dans le HTML. L'« attaque » n'était qu'une mise à jour bénigne, mais SRI a fait son travail. La solution était simple : générer un nouveau hash pour la police mise à jour et déployer la modification.
Leçon : SRI impose un versionnage strict. Il vous protège des modifications malveillantes et des mises à jour inattendues en amont, vous forçant à être intentionnel sur les ressources que vous utilisez.
Erreurs et pièges courants
- Oublier
crossorigin="anonymous". C'est l'erreur n°1. Sans cela, le navigateur n'a pas la permission CORS d'inspecter la ressource, donc par sécurité, il la bloque tout simplement. Aucune vérification d'intégrité n'a lieu. Votre script ou votre style ne se charge pas. - Hasher la mauvaise chose. Vous devez hasher le contenu exact du fichier que le navigateur reçoit. Ne hashez pas une version locale et non compressée d'un script si vous pointez vers la version minifiée sur le CDN. Ne hashez pas l'URL elle-même. Vous avez besoin du hash du corps du fichier.
- Utiliser des algorithmes de hash faibles. MD5 et SHA-1 ont des vulnérabilités connues et ne doivent pas être utilisés à des fins de sécurité. La spécification exige que les navigateurs prennent en charge au moins SHA-256, SHA-384 et SHA-512. Tenez-vous-en à ceux-là.
- Ne pas mettre à jour le hash après une mise à jour légitime. SRI est une fonctionnalité, pas un bug. Si le fichier auquel vous liez est mis à jour pour une raison quelconque, vous devez générer un nouveau hash d'intégrité et mettre à jour votre attribut
integritydans le HTML. Ne pas le faire entraînera le blocage de la ressource. - Penser que ça protège votre propre serveur. SRI est conçu pour valider les ressources tierces. Si un attaquant a compromis votre serveur au point de pouvoir modifier vos fichiers HTML, il peut simplement changer le hash SRI pour qu'il corresponde à son script malveillant. Ça n'apporte aucun avantage pour les ressources de même origine (same-origin).
Pourquoi vous devriez garder ça à l'œil
Vous devriez penser à la SRI chaque fois que vous écrivez <script src="..."> ou <link rel="stylesheet" href="..."> qui pointe vers un domaine que vous ne contrôlez pas.
C'est un élément fondamental de la sécurité web moderne. Dans un monde bâti sur NPM, les CDN et un enchevêtrement complexe de dépendances tierces, votre chaîne d'approvisionnement est une énorme surface d'attaque. La SRI est l'un des outils les plus simples et les plus efficaces pour renforcer cette surface. C'est votre première ligne de défense contre un CDN compromis. Associé à une Content Security Policy (CSP), il offre une protection robuste et à plusieurs niveaux.
Ajouter la SRI prend quelques secondes de plus lorsque vous ajoutez une ressource, mais ça peut vous éviter un monde de problèmes plus tard. Ça transforme un exploit silencieux et dangereux en un échec bruyant mais sans danger.
Pour aller plus loin
- MDN Web Docs: Subresource Integrity - La référence définitive pour les développeurs.
- W3C Recommendation: Subresource Integrity - La spécification technique officielle. Si vous voulez plonger au plus profond, c'est par ici.
- Can I use... Subresource Integrity - Tableau de compatibilité des navigateurs à jour pour la SRI.
- Wikipédia : Fonction de hachage cryptographique - Pour mieux comprendre la magie de l'« empreinte » derrière la SRI.
- Scott Helme: Subresource Integrity - Un excellent article de blog d'un expert en sécurité sur le quoi, le pourquoi et le comment (en anglais).