La politique de sécurité du World Wide Web est ancrée dans la politique de même origine. Par exemple, le code de www.jb51.net ne peut accéder qu'aux données de www.jb51.net, mais n'a pas l'autorisation d'accéder à http://www.baidu.com. Chaque origine est isolée du reste du réseau, créant ainsi un bac à sable sécurisé pour les développeurs. C’est parfait en théorie, mais les attaquants ont désormais trouvé des moyens intelligents de compromettre ce système.
Il s'agit d'une attaque de script intersite XSS, qui contourne la politique de même origine via de faux contenus et des clics leurres. Il s’agit d’un gros problème, et si un attaquant réussit à injecter du code, une quantité considérable de données utilisateur peut être divulguée.
Nous introduisons maintenant une nouvelle stratégie de défense de sécurité efficace pour atténuer ce risque, à savoir la politique de sécurité du contenu (CSP).
Source Whitelist
Le cœur de l'attaque XSS est que le navigateur ne peut pas distinguer si le script est injecté par un tiers ou s'il fait réellement partie de votre application. Par exemple, le bouton Google 1 chargera et exécutera le code de https://apis.google.com/js/plusone.js, mais nous ne pouvons pas nous attendre à déterminer à partir de l'image sur le navigateur que le code provient réellement d'apis.google. .com , encore une fois à partir de apis.evil.example.com. Le navigateur télécharge et exécute du code arbitraire sur les requêtes de page, quelle que soit son origine.
CSP définit l'en-tête HTTP Content-Security-Policy pour vous permettre de créer une liste blanche de sources fiables afin que le navigateur exécute et restitue uniquement les ressources de ces sources, plutôt que de faire aveuglément confiance à tout le contenu fourni par le serveur. Même si un attaquant parvient à trouver une vulnérabilité pour injecter un script, celui-ci ne sera pas exécuté car la source n'est pas incluse dans la liste blanche.
En prenant le bouton Google 1 ci-dessus comme exemple, parce que nous pensons que apis.google.com fournit du code valide, ainsi que nous-mêmes, nous pouvons définir une politique qui permet au navigateur d'exécuter uniquement les scripts de l'un des deux suivants sources.
Content-Security-Policy:script-src 'self' https://apis.google.com
N'est-ce pas très simple ? script-src peut contrôler les autorisations liées au script pour la page spécifiée. De cette façon, le navigateur téléchargera et exécutera uniquement les scripts de http://apis.google.com et de cette page elle-même.
Une fois que nous avons défini cette stratégie, le navigateur générera une erreur lorsqu'il détectera le code injecté (notez de quel navigateur il s'agit).
La politique de sécurité du contenu s'applique à toutes les ressources couramment utilisées.
Bien que les ressources de script constituent le risque de sécurité le plus évident, CSP fournit également un riche ensemble d'instructions qui permettent à la page de contrôler le chargement de divers types de ressources, telles que types suivants :
content-src : limite le type de connexion (tel que XHR, WebSockets et EventSource)
font-src : contrôle la source des polices Web. Par exemple, les polices Web de Google peuvent être utilisées via font-src https://themes.googleusercontent.com.
frame-src : répertorie les sources des frames qui peuvent être intégrées. Par exemple, frame-src https://youtube.com autorise uniquement l'intégration de vidéos YouTube. .
img-src : Définit la source des images chargeables.
media-src : Restreindre les sources vidéo et audio.
object-src : restreindre la source de Flash et d'autres plug-ins.
style-src : similaire à Script-src, mais s'applique uniquement aux fichiers CSS.
Par défaut, tous les paramètres sont activés sans aucune restriction. Vous pouvez séparer plusieurs directives par des points-virgules, mais sous la forme script-src https://host1.com;script-src https://host2.com, la deuxième directive sera ignorée. La bonne façon de l'écrire est script-src https://host1.com https://host2.com.
Par exemple, si vous avez une application qui doit charger toutes les ressources d'un réseau de diffusion de contenu (CDN, tel que https://cdn.example.net), et que vous savez qu'il n'existe aucun contenu qui ne nécessite n'importe quel cadre ou plug-in, votre stratégie pourrait être la suivante :
Content-Security-Policy:default-src https://cdn.example.net; frame-src 'none';
Détails
J'utilise dans l'exemple L'en-tête HTTP est Content-Security-Policy, mais les navigateurs modernes fournissent déjà un support via des préfixes : Firefox utilise x-Content-Security-Policy, WebKit utilise X-WebKit-CSP. Il y aura une transition progressive vers des normes unifiées à l’avenir.
Des stratégies peuvent être définies en fonction de chaque page différente, ce qui offre une grande flexibilité. Parce que certaines pages de votre site peuvent avoir des boutons Google 1, tandis que d'autres non.
La liste des sources de chaque directive peut être assez flexible, vous pouvez spécifier le modèle (data :, https :), ou spécifier le nom d'hôte dans une plage (example.com, qui correspond à n'importe quelle origine, n'importe quel modèle et n'importe quel port sur l'hôte), ou spécifiez un URI complet (https://example.com:443, spécifiquement le protocole https, le nom de domaine example.com, le port 443).
Il y a quatre autres mots-clés que vous pouvez utiliser dans votre liste de sources :
"none" : vous pourriez vous attendre à ne trouver aucune correspondance
"self" : le même que la source actuelle, mais sans sous-domaines
"unsafe- inline " : autorise Javascript et CSS en ligne
"unsafe-eval" : autorise les mécanismes de texte vers JS tels que eval
Veuillez noter que ces mots-clés doivent être cités.
Bac à sable
Il y a une autre directive qui mérite d'être discutée ici : le bac à sable. Elle est quelque peu incompatible avec d'autres instructions. Elle contrôle principalement les actions entreprises sur la page, plutôt que les ressources que la page peut charger. Si cet attribut est défini, la page se comportera comme un cadre avec l'attribut sandbox défini. Cela a un large éventail d'effets sur la page, comme empêcher l'envoi de formulaires, etc. Cela dépasse un peu le cadre de cet article, mais vous pouvez trouver plus d'informations dans le chapitre « Paramètres des indicateurs du bac à sable » de la spécification HTML5.
Code en ligne nuisible
CSP est basé sur la liste blanche des sources, mais il ne peut pas résoudre la plus grande source d'attaques XSS : l'injection de scripts en ligne. Si un attaquant peut injecter une balise de script (
) contenant du code nuisible, le navigateur ne dispose pas d'un bon mécanisme pour distinguer cette balise. CSP ne peut résoudre ce problème qu'en désactivant complètement les scripts en ligne. Cette interdiction inclut non seulement les balises de script intégrées dans les scripts, mais également les gestionnaires d'événements en ligne et les URL javascrpt:. Vous devez placer le contenu de la balise de script dans un fichier externe et remplacer javascript: et
par les méthodes addEventListener appropriées. Par exemple, vous pourriez réécrire la forme suivante :
Suis-je incroyable ?
sous la forme suivante :
Suis-je incroyable ?
// Amazing.js
function doAmazingThings() {
alert('VOUS SUIS INCROYABLE !');
>
document. addEventListener('DOMContentReady', function () {
document.getElementById('amazing')
.addEventListener('click', doAmazingThings);
});
Que vous utilisiez CSP ou non, le le code ci-dessus présente en réalité de plus grands avantages. Le JavaScript en ligne mélange complètement la structure et le comportement, et vous ne devriez pas le faire. De plus, les ressources externes sont plus faciles à mettre en cache par les navigateurs, plus faciles à comprendre pour les développeurs et plus faciles à compiler et à compresser. Si vous utilisez du code externe, vous écrirez un meilleur code.
Les styles en ligne doivent être traités de la même manière, les attributs de style et les balises de style doivent être extraits dans des feuilles de style externes. Cela évite toutes sortes de méthodes magiques de fuite de données.
Si vous devez disposer de scripts et de styles en ligne, vous pouvez définir la valeur "unsafe-inline" pour l'attribut script-src ou style-src. Mais ne faites pas cela. La désactivation des scripts en ligne est la plus grande garantie de sécurité fournie par CSP. La désactivation des styles en ligne peut rendre votre application plus sécurisée et plus robuste. C'est un compromis, mais cela en vaut la peine.
Eval
Même si l'attaquant ne peut pas injecter directement le script, il peut tromper votre application en convertissant le texte inséré en un script exécutable et en s'exécutant. eval() , newFunction() , setTimeout([string], ...) et setInterval([string], ...) peuvent tous être des vecteurs de ce danger. La stratégie de CSP face à ce risque consiste à bloquer entièrement ces vecteurs.
Cela a quelques implications sur la façon dont vous créez vos applications :
Analysez JSON via le JSON.parse intégré au lieu de vous fier à eval. Les navigateurs après IE8 prennent en charge les opérations JSON locales, ce qui est totalement sûr.
Réécrivez la façon dont vous appelez setTimeout et setInterval en utilisant des fonctions en ligne au lieu de chaînes. Par exemple :
setTimeout("document.querySelector('a').style.display = 'none';", 10);
Peut être réécrit comme :
setTimeout(function () { document. querySelector ('a').style.display = 'none'; }, 10);
Évitez les modèles en ligne au moment de l'exécution : de nombreuses bibliothèques de modèles utilisent new Function() pour accélérer la génération de modèles. C'est idéal pour les programmes dynamiques, mais risqué pour le texte malveillant.
Rapports<script>sendMyDataToEvilDotCom();</script> La capacité de CSP à bloquer les ressources non fiables côté serveur est excellente pour les utilisateurs, mais c'est également formidable pour nous de recevoir les différentes notifications envoyées au serveur afin que nous puissions identifier et corriger toute injection de script malveillant. Pour ce faire, vous pouvez demander au navigateur d'envoyer un rapport d'interception au format JSON à une certaine adresse via la directive report-uri. <script><br /> function doAmazingThings() {<br /> alert('YOU AM AMAZING!');<br /> }<br /></script>Content-Security-Policy : default-src 'self' ; report-uri /my_amazing_csp_report_parser ;Le rapport ressemblera à ceci :
{
"csp-report": {
"document-uri": "http://example.org/page.html",
"referrer" : "http://evil.example.com/",
"blocked-uri": "http://evil.example.com/evil.js",
"violated-directive": " script -src 'self' https://apis.google.com",
"original-policy": "script-src 'self' https://apis.google.com; report-uri http:// exemple .org/my_amazing_csp_report_parser"
}
>
Les informations qu'il contient vous aideront à identifier la situation d'interception, y compris la page où l'interception a eu lieu (document-uri), le référent de la page et le les ressources qui violent la politique de la page ( uri bloqué), la directive violée et toutes les politiques de sécurité du contenu de la page (politique d'origine).
Utilisation dans le monde réel
CSP est désormais disponible dans Chrome 16 et Firefox 4, et sa prise en charge devrait être limitée dans IE10. Safari ne le prend pas encore en charge, mais des versions nocturnes de WebKit sont disponibles, alors attendez-vous à ce que Safari le prenne en charge lors de la prochaine itération.
Examinons quelques cas d'utilisation courants :
Cas pratique 1 : Widget de réseau social
Le bouton Google 1 inclut des scripts de https://apis.google.com et intégrés à partir de l'iframe https:// pour plusone .google.com. Votre stratégie doit inclure ces sources pour utiliser le bouton Google 1. La stratégie la plus simple est script-src https://apis.google.com ; frame-src https://plusone.google.com. Vous devez également vous assurer que les extraits JS fournis par Google sont stockés dans des fichiers JS externes.
Il existe de nombreuses solutions d’implémentation pour le bouton J’aime de Facebook. Je vous recommande de vous en tenir à la version iframe car elle reste bien isolée du reste de votre site. Cela nécessite l'utilisation de la directive frame-src https://facebook.com. Veuillez noter que par défaut, le code iframe fourni par Facebook utilise le chemin relatif //facebook.com Veuillez changer ce code en https://facebook.com Vous ne pouvez pas utiliser HTTP si nécessaire.
Le bouton Tweet de Twitter repose sur un script et un cadre, tous deux provenant de https://platform.twitter.com (Twitter fournit des URL relatives par défaut, veuillez modifier le code pour spécifier HTTPS lors de la copie).
D'autres plateformes ont des situations similaires et peuvent être résolues de la même manière. Je recommande de définir default-src sur none, puis de vérifier la console pour vérifier les ressources dont vous avez besoin pour vous assurer que le widget fonctionne correctement.
Utiliser plusieurs widgets est très simple : il suffit de fusionner toutes les directives de stratégie et n'oubliez pas de conserver ensemble les paramètres d'une même directive. Si vous souhaitez utiliser les trois widgets ci-dessus, la stratégie ressemblera à ceci :
script-src https://apis.google.com https://platform.twitter.com frame-src https:// plusone ; .google.com https://facebook.com https://platform.twitter.com
Cas pratique 2 : Défense
Supposons que vous visitiez le site Web d'une banque et que vous souhaitiez vous assurer que seules les ressources dont vous avez besoin sont chargées. Dans ce cas, commencez par définir une autorisation par défaut pour bloquer tout le contenu (default-src « aucun ») et créez la politique à partir de zéro.
Par exemple, le site Web d'une banque doit charger des images, des styles et des scripts à partir du CDN depuis https://cdn.mybank.net, et se connecter à https://api.mybank.com/ via XHR pour extraire diverses données. . Vous devez également utiliser des cadres, mais les cadres proviennent de pages locales non tierces. Il n'y a pas de Flash, de polices et autres contenus sur le site Web. Dans ce cas, l'en-tête CSP le plus strict que nous pouvons envoyer est :
Content-Security-Policy : default-src 'none' ; .mybank.net; img-src https://cdn.mybank.net; connect-src https://api.mybank.com; frame-src 'self'
Cas réel 3 : utiliser uniquement SSL
Un administrateur de forum sur les alliances souhaite que toutes les ressources soient chargées de manière sécurisée, mais ne souhaite pas écrire trop de code ; réécrire un grand nombre de scripts et de styles en ligne de forum tiers dépasse ses capacités. La politique suivante sera donc très utile :
Content-Security-Policy: default-src https:; script-src https: 'unsafe-inline'; style-src https: 'unsafe-inline'
Bien que par défaut -src spécifie https, les scripts et les styles ne sont pas automatiquement hérités. Chaque directive remplacera complètement le type de ressource par défaut.
Futur
Le groupe de travail sur la sécurité des applications Web du W3C formule les détails de la spécification de la politique de sécurité du contenu. La version 1.0 est sur le point d'entrer dans la phase de révision finale, et elle est très proche de ce qui est décrit dans cet article. Le groupe de diffusion public-webappsec@ discute de la version 1.1 et les fabricants de navigateurs travaillent également dur pour consolider et améliorer la mise en œuvre de CSP.
CSP 1.1 possède quelques fonctionnalités intéressantes sur le plan de travail qui méritent d'être répertoriées séparément :
Ajout de politiques via des balises méta : la méthode préférée pour définir CSP consiste à utiliser les en-têtes HTTP, qui sont très utiles, mais les définir via des balises ou des scripts est plus simple. , mais pour l'instant Pas encore finalisé. WebKit a implémenté la fonctionnalité de définition des autorisations via des méta-éléments, vous pouvez donc maintenant essayer les paramètres suivants dans Chrome : ajoutez
Vous pouvez même ajouter des stratégies via un script au moment de l'exécution.
API DOM : Si la prochaine itération de CSP ajoute cette fonctionnalité, vous pouvez interroger la politique de sécurité actuelle de la page via Javascript et l'ajuster en fonction de différentes situations. Par exemple, l'implémentation de votre code peut être légèrement différente si eval() est disponible. Ceci est très utile pour les auteurs du framework JS ; et comme la spécification de l'API est actuellement très incertaine, vous pouvez trouver la dernière itération dans le chapitre Interface de script du projet de spécification.
Nouvelles directives : de nombreuses nouvelles directives sont en cours de discussion, notamment script-nonce : seuls les éléments de script explicitement spécifiés peuvent utiliser des scripts en ligne ; les types de plugin : cela limitera le type de plugins ; form-action : permet au formulaire de se soumettre uniquement à une source spécifique.
Si vous êtes intéressé par des discussions sur ces futures fonctionnalités, vous pouvez lire les archives de la liste de diffusion ou rejoindre la liste de diffusion.
Cet article est traduit de : http://www.html5rocks.com/en/tutorials/security/content-security-policy/
Extrait de : le blog de Jiang Yujie