Script intersites (XSS) la possibilité d'injecter des scripts malveillants dans une application Web, les plus vulnérabilités de sécurité sur le Web depuis plus de dix ans.
Content Security Policy (CSP)
est une couche de sécurité supplémentaire
qui permet d'atténuer les attaques XSS. Pour configurer un CSP,
ajouter l'en-tête HTTP Content-Security-Policy
à une page Web et définir des valeurs qui
contrôler les ressources que le user-agent peut charger pour cette page.
Cette page explique comment utiliser une CSP basée sur des nonces ou des hachages pour limiter les attaques XSS. Au lieu des CSP basées sur une liste d'autorisation d'hôtes, couramment utilisés, qui quittent souvent la page exposés aux XSS, car ils peuvent être contrôlés dans la plupart des configurations.
Terme clé: un nonce est un nombre aléatoire utilisé une seule fois, que vous pouvez utiliser pour marquer un
Balise <script>
approuvée.
Terme clé: une fonction de hachage est une fonction mathématique qui convertit une entrée.
en une valeur numérique compressée appelée hachage. Vous pouvez utiliser un hachage
(par exemple, SHA-256) pour marquer une
Balise <script>
approuvée.
Une Content Security Policy basée sur des nonces ou des hachages est souvent appelée CSP stricte. Lorsqu'une application utilise une CSP stricte, les pirates informatiques qui trouvent du code HTML les failles d'injection ne peuvent généralement pas les utiliser pour forcer le navigateur à s'exécuter des scripts malveillants dans un document vulnérable. En effet, une CSP stricte uniquement autorise les scripts hachés ou les scripts avec la valeur nonce correcte générée sur le pour que les pirates informatiques ne puissent pas exécuter le script sans connaître le bon nonce pour une réponse donnée.
Pourquoi devriez-vous utiliser une CSP stricte ?
Si votre site dispose déjà d'une CSP comme script-src www.googleapis.com
,
elle n'est probablement pas efficace
contre les sites intersites. Ce type de CSP est appelé
CSP par liste d'autorisation. Ils nécessitent beaucoup de
personnalisation et peuvent être
contrôlés par les pirates informatiques.
Les CSP strictes basées sur des nonces ou des hachages cryptographiques évitent ces pièges.
Structure CSP stricte
Une stratégie de sécurité du contenu stricte de base utilise l'une des réponses HTTP suivantes en-têtes:
CSP stricte basée sur nonce
Content-Security-Policy:
script-src 'nonce-{RANDOM}' 'strict-dynamic';
object-src 'none';
base-uri 'none';
CSP stricte basée sur le hachage
Content-Security-Policy:
script-src 'sha256-{HASHED_INLINE_SCRIPT}' 'strict-dynamic';
object-src 'none';
base-uri 'none';
Les propriétés suivantes rendent une CSP comme celle-ci "stricte" et donc sécurisés:
- Elle utilise des nonces
'nonce-{RANDOM}'
ou des hachages'sha256-{HASHED_INLINE_SCRIPT}'
. pour indiquer les balises<script>
dans lesquelles le développeur du site fait confiance pour s'exécuter dans le navigateur de l'utilisateur. - Elle définit
'strict-dynamic'
. pour réduire le travail de déploiement d'un CSP basé sur des nonces ou des hachages en permettant l’exécution de scripts créés par un script de confiance. De plus, débloque l'utilisation de la plupart des widgets et bibliothèques JavaScript tiers. - Il n'est pas basé sur les listes d'autorisation d'URL. Il ne souffre donc pas contournements courants de CSP.
- Il bloque les scripts intégrés non fiables tels que les gestionnaires d'événements intégrés ou
javascript:
. URI. - Elle limite
object-src
pour désactiver les plug-ins dangereux tels que Flash. - Elle limite
base-uri
pour bloquer l'injection des balises<base>
. Cela permet d'éviter les attaquants de modifier l’emplacement des scripts chargés à partir d’URL relatives.
Adopter une CSP stricte
Pour adopter une CSP stricte, vous devez:
- Déterminez si votre application doit définir un CSP basé sur des nonce ou un hachage.
- Copiez la CSP depuis la section Structure de CSP stricte et configurez-la en tant qu'en-tête de réponse dans votre application.
- Refactoriser les modèles HTML et le code côté client pour supprimer les modèles incompatible avec CSP.
- Déployez votre CSP.
Vous pouvez utiliser Lighthouse
(version 7.3.0 ou ultérieure avec l'option --preset=experimental
) Audit des bonnes pratiques
tout au long du processus pour vérifier si votre site dispose d'une CSP,
suffisamment stricte pour être efficace
contre les scripts intersites.
Étape 1: Déterminez si vous avez besoin d'une CSP basée sur un nonce ou un hachage
Voici comment fonctionnent les deux types de CSP strictes:
CSP basée sur le nonce
Avec un CSP basé sur des nonce, vous générez un nombre aléatoire au moment de l'exécution et vous l'incluez dans votre CSP et l'associer à chaque balise de script de votre page. Un pirate informatique ne peuvent pas inclure ni exécuter un script malveillant sur votre page, car ils auraient besoin deviner le nombre aléatoire correct pour ce script. Cela ne fonctionne que si le nombre n'est pas devinable et est généré lors de l'exécution pour chaque réponse.
Utilisez une CSP basée sur des nonce pour les pages HTML affichées sur le serveur. Pour ces pages, vous pouvez créer un nouveau nombre aléatoire pour chaque réponse.
CSP basée sur le hachage
Dans le cas d'une CSP basée sur un hachage, le hachage de chaque tag de script intégré est ajouté à la CSP. Chaque script est associé à un hachage différent. Un attaquant ne peut pas inclure ou exécuter dans votre page, car le hachage de ce script devrait se trouver CSP pour l'exécution.
Utilisez un CSP basé sur le hachage pour les pages HTML diffusées en mode statique ou les pages qui doivent être mis en cache. Par exemple, vous pouvez utiliser une CSP basée sur un hachage pour le Web monopage. des applications créées avec des frameworks comme Angular, React ou d'autres, qui sont diffusées de manière statique sans affichage côté serveur.
Étape 2: Définissez une CSP stricte et préparez vos scripts
Lorsque vous configurez une CSP, vous disposez de plusieurs options:
- Mode Rapport uniquement (
Content-Security-Policy-Report-Only
) ou mode application forcée (Content-Security-Policy
). En mode rapport uniquement, la CSP ne bloque de ressources. Ainsi, votre site ne tombera jamais en panne, mais vous pourrez voir les erreurs des rapports sur tous les éléments qui auraient été bloqués. Au niveau local, lorsque vous dans la configuration de votre CSP, cela n'a pas vraiment d'importance, car les deux modes vous indiquent dans la console du navigateur. Le mode application forcée peut vous aider à trouver ressources que votre brouillon de bloc CSP peut avoir, car le blocage d'une ressource peut la page semble défectueuse. Le mode Rapport uniquement devient plus utile plus tard dans le processus (voir l'étape 5). - En-tête ou balise HTML
<meta>
. Pour le développement local, un tag<meta>
peut être plus pratique pour ajuster votre CSP et voir rapidement son impact sur votre site. Toutefois:- Par la suite, lors du déploiement de votre CSP en production, nous vous recommandons de le définir un en-tête HTTP.
- Si vous souhaitez définir votre CSP en mode "Rapport uniquement", vous devez le définir en tant que car les balises Meta CSP ne sont pas compatibles avec le mode rapport uniquement.
Définissez la réponse HTTP Content-Security-Policy
suivante
dans votre application:
Content-Security-Policy: script-src 'nonce-{RANDOM}' 'strict-dynamic'; object-src 'none'; base-uri 'none';
Générer un nonce pour CSP
Un nonce est un nombre aléatoire utilisé une seule fois par chargement de page. Un nonce CSP ne peut atténuer les failles XSS que si les pirates informatiques ne peuvent pas deviner la valeur du nonce. A Le nonce CSP doit être:
- Une valeur aléatoire cryptographiquement forte (dans l'idéal, d'une longueur de plus de 128 bits)
- Générées pour chaque réponse
- Encodage en base64
Voici quelques exemples d'ajout d'un nonce CSP dans les frameworks côté serveur:
- Django (python)
- Express (JavaScript):
const app = express(); app.get('/', function(request, response) { // Generate a new random nonce value for every response. const nonce = crypto.randomBytes(16).toString("base64"); // Set the strict nonce-based CSP response header const csp = `script-src 'nonce-${nonce}' 'strict-dynamic'; object-src 'none'; base-uri 'none';`; response.set("Content-Security-Policy", csp); // Every <script> tag in your application should set the `nonce` attribute to this value. response.render(template, { nonce: nonce }); });
Ajouter un attribut nonce
aux éléments <script>
Avec une CSP basée sur des nonce, chaque élément <script>
doit
comportent un attribut nonce
qui correspond au nonce aléatoire
spécifiée dans l'en-tête CSP. Tous les scripts peuvent avoir le même
nonce La première étape consiste à ajouter ces attributs à tous les scripts afin que
CSP les autorise.
Définissez la réponse HTTP Content-Security-Policy
suivante
dans votre application:
Content-Security-Policy: script-src 'sha256-{HASHED_INLINE_SCRIPT}' 'strict-dynamic'; object-src 'none'; base-uri 'none';
Pour plusieurs scripts intégrés, la syntaxe est la suivante:
'sha256-{HASHED_INLINE_SCRIPT_1}' 'sha256-{HASHED_INLINE_SCRIPT_2}'
Charger dynamiquement des scripts issus d'une source
Étant donné que les hachages CSP sont compatibles avec les navigateurs uniquement pour les scripts intégrés, vous devez charger tous les scripts tiers de manière dynamique à l'aide d'un script intégré. Le hachage des scripts source n'est pas compatible avec tous les navigateurs.
<script> var scripts = [ 'https://example.org/foo.js', 'https://example.org/bar.js']; scripts.forEach(function(scriptUrl) { var s = document.createElement('script'); s.src = scriptUrl; s.async = false; // to preserve execution order document.head.appendChild(s); }); </script>
<script src="https://example.org/foo.js"></script> <script src="https://example.org/bar.js"></script>
Remarques concernant le chargement du script
L'exemple de script intégré ajoute s.async = false
pour garantir
que foo
exécute avant bar
, même si
bar
se charge en premier. Dans cet extrait, s.async = false
ne bloque pas l'analyseur pendant le chargement des scripts, car les scripts sont
ajoutés de manière dynamique. L'analyseur s'arrête uniquement pendant l'exécution des scripts,
c'est le cas pour async
scripts. Toutefois, avec cet extrait,
Gardez à l'esprit les points suivants:
-
L'un des scripts ou les deux peuvent s'exécuter avant la fin du document
en cours de téléchargement. Si vous souhaitez que le document soit prêt au moment
scripts s'exécutent, attendez l'événement
DOMContentLoaded
avant de vous ajoutez les scripts. Si cela entraîne un problème de performances le téléchargement des scripts ne commence pas assez tôt, utilisez des balises de préchargement plus tôt sur la page. -
defer = true
n'a aucun effet. Si vous en avez besoin, , exécutez le script manuellement si nécessaire.
Étape 3: Refactoriser les modèles HTML et le code côté client
Gestionnaires d'événements intégrés (tels que onclick="…"
et onerror="…"
) et URI JavaScript
(<a href="javascript:…">
) permet d'exécuter des scripts. Cela signifie qu'un
un pirate informatique qui trouve un bug XSS peut injecter ce type de code HTML et exécuter des
JavaScript. Une CSP basée sur des nonce ou un hachage interdit l'utilisation de ce type de balisage.
Si votre site utilise l'un de ces formats, vous devrez les refactoriser pour qu'ils soient plus sûrs
alternatives.
Si vous avez activé CSP à l'étape précédente, vous pourrez voir les cas de non-respect CSP dans la console chaque fois que CSP bloque un schéma incompatible.
Dans la plupart des cas, la solution est simple:
Refactoriser les gestionnaires d'événements intégrés
<span id="things">A thing.</span> <script nonce="${nonce}"> document.getElementById('things').addEventListener('click', doThings); </script>
<span onclick="doThings();">A thing.</span>
Refactoriser les URI javascript:
<a id="foo">foo</a> <script nonce="${nonce}"> document.getElementById('foo').addEventListener('click', linkClicked); </script>
<a href="javascript:linkClicked()">foo</a>
Supprimer eval()
de votre code JavaScript
Si votre application utilise eval()
pour convertir les sérialisations de chaînes JSON en JavaScript
, vous devez refactoriser ces instances vers JSON.parse()
, qui est également
plus vite.
Si vous ne pouvez pas supprimer toutes les utilisations de eval()
, vous pouvez toujours définir une valeur stricte basée sur des nonces
CSP, mais vous devez utiliser le mot clé CSP 'unsafe-eval'
, ce qui rend votre
est un peu moins sécurisée.
Vous trouverez ces exemples et d'autres exemples de refactorisation dans cette CSP stricte codelab:
Étape 4 (facultative): Ajoutez des créations de remplacement pour assurer la compatibilité avec les anciennes versions de navigateur
Si vous devez assurer la compatibilité avec d'anciennes versions de navigateur:
- L'utilisation de
strict-dynamic
nécessite l'ajout dehttps:
en remplacement pour une version antérieure. de Safari. Lorsque vous procédez ainsi:- Tous les navigateurs compatibles avec
strict-dynamic
ignorent la création de remplacementhttps:
. donc cela ne réduira pas la force de la règle. - Dans les anciens navigateurs, les scripts externes ne peuvent être chargés que s'ils proviennent
une origine HTTPS. Cette méthode est moins sécurisée
qu'une CSP stricte, mais elle
empêche certaines causes XSS courantes telles que les injections d'URI
javascript:
.
- Tous les navigateurs compatibles avec
- Pour assurer la compatibilité avec les très anciennes versions de navigateur (4 ans et plus), vous pouvez ajouter
unsafe-inline
en remplacement. Tous les navigateurs récents ignorentunsafe-inline
si un nonce ou un hachage CSP est présent.
Content-Security-Policy:
script-src 'nonce-{random}' 'strict-dynamic' https: 'unsafe-inline';
object-src 'none';
base-uri 'none';
Étape 5: Déployez votre CSP
Après avoir vérifié que votre CSP ne bloque pas les scripts légitimes dans votre environnement de développement local, vous pouvez déployer votre CSP en préproduction, de production:
- (Facultatif) Déployez votre CSP en mode rapport uniquement à l'aide de
En-tête
Content-Security-Policy-Report-Only
. Le mode Rapport uniquement est pratique pour tester une modification potentiellement destructive comme un nouveau fournisseur de services cloud en production commencer à appliquer des restrictions liées aux CSP. En mode rapport uniquement, votre CSP ne affectent le comportement de votre application, mais le navigateur génère quand même des erreurs dans la console. et les signalements de violations lorsqu'il rencontre des formats incompatibles avec votre CSP, afin que vous puissiez voir ce qui n'aurait pas fonctionné pour vos utilisateurs finaux. Pour plus consultez API Reporting. - Si vous êtes sûr que votre CSP ne perturbera pas
votre site pour les utilisateurs finaux,
Déployez votre CSP à l'aide de l'en-tête de réponse
Content-Security-Policy
. Mer nous vous recommandons de définir votre CSP à l'aide d'un en-tête HTTP côté serveur, car il est plus qu'un tag<meta>
. Une fois cette étape terminée, votre CSP commence protéger votre application contre les attaques XSS.
Limites
Une CSP stricte fournit généralement
un niveau de sécurité supplémentaire élevé qui aide à
pour atténuer les effets de XSS. Dans la plupart des cas, CSP réduit
considérablement la surface d'attaque,
rejetant les modèles dangereux tels que les URI javascript:
. Toutefois, en fonction du type
de CSP que vous utilisez (nonces, hachages, avec ou sans 'strict-dynamic'
), il y a
CSP ne protège pas votre application également:
- Si vous créez un nonce de script, mais qu'il y a une injection directement dans le corps ou
Paramètre
src
de cet élément<script>
. - S'il y a des injections aux emplacements des scripts créés dynamiquement
(
document.createElement('script')
), y compris dans les fonctions de la bibliothèque qui créentscript
nœuds DOM en fonction des valeurs de leurs arguments. Ce comprend des API courantes telles que.html()
de jQuery, ainsi que.get()
et.post()
dans jQuery < 3.0. - S'il existe des injections de modèles dans d'anciennes applications AngularJS Un pirate informatique injectable dans un modèle AngularJS, peut l'utiliser pour exécuter du code JavaScript arbitraire.
- Si la règle contient
'unsafe-eval'
, des injections danseval()
,setTimeout()
et quelques autres API rarement utilisées.
Les développeurs et les ingénieurs en sécurité doivent accorder une attention particulière des schémas lors des revues de code et des audits de sécurité. Vous trouverez plus d'informations sur ces cas dans l'article Content Security Policy: A Réussit entre la sécurisation renforcée et son atténuation.
Documentation complémentaire
- CSP est mort. Longue vie à CSP ! sur l'insécurité des listes blanches et l'avenir de Content Security Policy
- CSP Evaluator
- Conférence LocoMoco : la stratégie de sécurité des contenus : le chaos entre le renforcement et l'atténuation des risques
- Conférence Google I/O: Sécuriser les applications Web grâce à des fonctionnalités de plate-forme modernes