Tous les articles

strict-dynamic expliqué, abandonnez les allowlists de hosts pour une CSP stricte

CentralCSP Team ·

Dernière mise à jour:

Les allowlists de hosts dans une politique de sécurité du contenu (CSP) donnent un sentiment de sécurité qui, le plus souvent, n'en est pas un. Vous listez les domaines d'où viennent vos scripts, mais vous faites confiance à chaque fichier de chacun de ces domaines, y compris ceux que vous n'y avez pas mis. Il suffit d'un CDN de confiance qui sert aussi un fichier accessible à un attaquant, et l'allowlist est contournée. Le mot-clé 'strict-dynamic' est la réponse moderne : au lieu de faire confiance à des domaines, vous faites confiance à des scripts précis que vous marquez, et vous laissez ces scripts se porter garants de ceux qu'ils chargent.

Le problème que résout strict-dynamic

Prenez une politique comme script-src 'self' https://cdn.example.com. Elle fait confiance à chaque script de ce CDN, et par extension à chaque script que ces scripts chargent. Les chercheurs en sécurité ont montré à de nombreuses reprises que les grandes allowlists sont contournables : un endpoint JSONP, une redirection ouverte ou une bibliothèque obsolète hébergée sur un domaine de l'allowlist peuvent être détournés en exécution de script arbitraire, que la politique autorise sans broncher. Plus vous ajoutez de domaines pour que le site continue de fonctionner, plus la politique s'affaiblit.

'strict-dynamic' retire le domaine de la décision de confiance. Le navigateur cesse de demander « ce script vient-il d'un host autorisé » et commence à demander « ce script a-t-il été cautionné », une question bien plus difficile à satisfaire pour un attaquant.

Comment ça marche

Vous marquez les scripts de confiance avec un nonce ou un hash, et vous ajoutez 'strict-dynamic' à script-src. Le navigateur fait confiance à ces scripts marqués et propage cette confiance à tout script qu'ils créent au runtime, tout en ignorant les host-sources et l'expression 'self' pour les scripts.

Content-Security-Policy:
    script-src 'nonce-r4nd0m' 'strict-dynamic';
    object-src 'none';
    base-uri 'none'

Le nonce est une nouvelle valeur aléatoire que votre serveur génère par réponse et place à la fois dans le header et sur chaque balise <script> de confiance (voir comment configurer un nonce selon le framework). 'strict-dynamic' indique alors qu'un script auquel le navigateur fait déjà confiance (parce qu'il portait le nonce) est autorisé à charger d'autres scripts, qui héritent de cette confiance. Un loader de confiance peut donc tirer les tiers dont il a besoin sans que vous énumériez le moindre host.

La confiance part du script marqué par le nonce et se propage vers l'extérieur, tandis que les allowlists de hosts sont ignorées pour les scripts :

strict-dynamic comparé à un simple nonce

Un nonce seul ne fait confiance qu'aux balises exactes sur lesquelles vous l'avez posé. Cela casse le schéma courant où un script de confiance en injecte dynamiquement un autre, un loader d'analytics qui ajoute un tracker, ou un tag manager qui écrit d'autres balises de script (voir GTM sous une CSP stricte avec Next.js). Sans 'strict-dynamic', ces scripts injectés n'ont pas de nonce et sont bloqués. Avec lui, ils sont autorisés parce que le script qui les a créés était de confiance. Cette propagation est précisément la raison d'ajouter le mot-clé en plus d'un nonce.

Ce qu'il ignore, et ce qui s'applique encore

Quand 'strict-dynamic' est présent, le navigateur ignore les host-sources, les sources de schéma, 'self' et 'unsafe-inline' pour les scripts ; la confiance ne découle que d'un nonce ou d'un hash. C'est pourquoi vous pouvez laisser une allowlist de hosts dans la politique pour les anciens navigateurs sans affaiblir les navigateurs modernes, qui se contentent de l'ignorer.

Conservez object-src 'none' et base-uri 'none' dans la politique quoi qu'il arrive. 'strict-dynamic' ne gouverne que les scripts, donc les plugins et une balise <base> détournée ne sont pas couverts, et ces deux directives ferment des contournements que la confiance des scripts ne couvre pas.

Support des navigateurs

'strict-dynamic' est largement supporté par les navigateurs actuels. Les anciens navigateurs qui ne comprennent pas le mot-clé l'ignorent et retombent sur l'allowlist de hosts, ce qui explique pourquoi vous pouvez déployer les deux : l'allowlist est un repli pour les moteurs anciens, pas le contrôle principal. Présentez-la ainsi plutôt que comme quelque chose à maintenir indéfiniment.

Voyez-le dans vos reports

Ne basculez pas une politique stricte à l'aveugle. Déployez-la d'abord en Report-Only et observez quels scripts seraient cassés, car un loader dynamique oublié peut faire tomber les analytics ou les paiements. CentralCSP collecte ces reports depuis le trafic réel, pour que vous confirmiez que la politique est sûre face à ce que les utilisateurs chargent réellement avant de l'appliquer.

Les violations issues du trafic réel, regroupées par directive et origine bloquée

Étapes suivantes

Déployez une CSP stricte en toute confiance.

Sources