Partager via


Utilisation de la stratégie de sécurité de contenu (CSP) pour contrôler les ressources qui peuvent être exécutées

Pour contrôler le contenu qui peut être exécuté par votre extension, dans le fichier de manifest.json l’extension, utilisez la content_security_policy clé et sa valeur de chaîne de stratégie, selon la syntaxe suivante :

{
    ...,
    "content_security_policy": "[policy string]"
    ...
}

Par exemple, voici la stratégie de sécurité du contenu par défaut, comme décrit ci-dessous dans Restrictions de stratégie par défaut :

{
    ...,
    "content_security_policy": "script-src 'self'; object-src 'self'; worker-src 'self'"
    ...
}

Pour atténuer une grande classe de problèmes potentiels de script intersites, le système d’extension Microsoft Edge intègre la stratégie de sécurité du contenu (CSP). Csp introduit des stratégies strictes qui rendent les extensions plus sécurisées par défaut, et vous permet de créer et d’appliquer des règles régissant les types de contenu qui peuvent être chargés et exécutés par vos extensions et applications.

En général, csp fonctionne comme un mécanisme de liste de blocs/d’autorisation pour les ressources chargées ou exécutées par votre extension. La définition d’une stratégie raisonnable pour votre extension vous permet d’examiner attentivement les ressources dont votre extension a besoin et de demander au navigateur de s’assurer qu’il s’agit des seules ressources auxquelles votre extension a accès. Les stratégies fournissent une sécurité au-delà des autorisations de l’hôte que votre extension demande ; il s’agit d’une couche supplémentaire de protection, et non d’un remplacement.

En revanche, dans une page web, une telle stratégie est définie via un en-tête HTTP ou via un meta élément. Mais à l’intérieur du système d’extension Microsoft Edge, un en-tête HTTP ou un meta élément n’est pas un mécanisme approprié.

Voir :

Restrictions de stratégie par défaut

Les packages qui ne définissent pas de manifest_version n’ont pas de stratégie de sécurité de contenu par défaut.

Les packages qui utilisent manifest_version ont la stratégie de sécurité de contenu par défaut suivante :

script-src 'self'; object-src 'self'; worker-src 'self'

La stratégie ajoute la sécurité en limitant les extensions et les applications de trois manières :

Le code comme celui-ci ne fonctionne pas :

alert(eval("foo.bar.baz"));
window.setTimeout("alert('hi')", 10);
window.setInterval("alert('hi')", 10);
new Function("return foo.bar.baz");

L’évaluation des chaînes de JavaScript comme celle-ci est un vecteur d’attaque XSS courant. Au lieu de cela, vous devez écrire du code comme suit :

alert(foo && foo.bar && foo.bar.baz);
window.setTimeout(function() { alert('hi'); }, 10);
window.setInterval(function() { alert('hi'); }, 10);
function() { return foo && foo.bar && foo.bar.baz };

JavaScript inline ne sont pas exécutés

Les javascripts inline ne sont pas exécutés. Cette restriction interdit à la fois les blocs inline <script> et les gestionnaires d’événements inline, tels que <button onclick="...">.

La première restriction supprime une énorme classe d’attaques de script intersites en vous rendant impossible d’exécuter accidentellement le script fourni par un tiers malveillant. Toutefois, cela vous oblige à écrire votre code avec une séparation propre entre le contenu et le comportement. Un exemple peut rendre cela plus clair. Vous pouvez essayer d’écrire une fenêtre contextuelle d’action de navigateur en tant que simple pop-up.html contenant les éléments suivants :

<!doctype html>
<html>
    <head>
        <title>My Awesome Pop-up!</title>
        <script>
            function awesome() {
                // do something awesome!
            }

            function totallyAwesome() {
                // do something TOTALLY awesome!
            }

            function clickHandler(element) {
                setTimeout("awesome(); totallyAwesome()", 1000);
            }

            function main() {
                // Initialization work goes here.
            }
        </script>
    </head>
    <body onload="main();">
        <button onclick="clickHandler(this)">
            Click for awesomeness!
        </button>
    </body>
</html>

Mais trois choses doivent changer pour que cela fonctionne comme vous l’attendez :

  • La clickHandler définition doit être déplacée dans un fichier JavaScript externe (popup.js peut être une bonne cible).

  • Les définitions du gestionnaire d’événements inline doivent être réécrites en termes de addEventListener et extraites dans popup.js. Si vous démarrez actuellement votre programme à l’aide de code tel que <body onload="main();">, envisagez de le remplacer par un raccordement à l’événement DOMContentLoaded du document ou à l’événement load de la fenêtre, en fonction de vos besoins. Utilisez le premier, car il se déclenche généralement plus rapidement.

  • L’appel setTimeout doit être réécrit pour éviter de convertir la chaîne "awesome(); totallyAwesome()" en JavaScript pour l’exécution.

Ces modifications peuvent ressembler à ce qui suit :

function awesome() {
    // Do something awesome!
}

function totallyAwesome() {
    // do something TOTALLY awesome!
}

function awesomeTask() {
    awesome();
    totallyAwesome();
}

function clickHandler(e) {
    setTimeout(awesomeTask, 1000);
}

function main() {
    // Initialization work goes here.
}

// Add event listeners once the DOM has fully loaded by listening for the
// `DOMContentLoaded` event on the document, and adding your listeners to
// specific elements when it triggers.
document.addEventListener('DOMContentLoaded', function () {
    document.querySelector('button').addEventListener('click', clickHandler);
    main();
});
<!doctype html>
<html>
    <head>
        <title>My Awesome Pop-up!</title>
        <script src="popup.js"></script>
    </head>
    <body>
        <button>Click for awesomeness!</button>
    </body>
</html>

Seules les ressources de script et d’objet locales sont chargées

Les ressources de script et d’objet ne peuvent être chargées qu’à partir du package d’extension, et non à partir du web à grande échelle. Cela garantit que votre extension exécute uniquement le code que vous avez spécifiquement approuvé, ce qui empêche un attaquant réseau actif de rediriger de manière malveillante votre demande pour une ressource.

Au lieu d’écrire du code qui dépend du chargement de jQuery (ou de toute autre bibliothèque) à partir d’un CDN externe, envisagez d’inclure la version spécifique de jQuery dans votre package d’extension. Autrement dit, au lieu de :

<!doctype html>
<html>
    <head>
        <title>My Awesome Pop-up!</title>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
    </head>
    <body>
        <button>Click for awesomeness!</button>
    </body>
</html>

Utilisez plutôt l’approche suivante. Téléchargez le fichier, incluez-le dans votre package et écrivez :

<!doctype html>
<html>
    <head>
        <title>My Awesome Pop-up!</title>
        <script src="jquery.min.js"></script>
    </head>
    <body>
        <button>Click for awesomeness!</button>
    </body>
</html>

Assouplissement de la stratégie par défaut

Vous pouvez autoriser l’exécution des types de script suivants :

Les détails sont ci-dessous.

Script inline

Les scripts inline peuvent être autorisés en spécifiant le hachage codé en base64 du code source dans la stratégie. Ce hachage doit être préfixé par l’algorithme de hachage utilisé (sha256, sha384 ou sha512). Pour obtenir un exemple, consultez Utilisation du hachage W3C > pour <les éléments de script>.

Script distant

Si vous avez besoin de ressources JavaScript ou d’objets externes, vous pouvez assouplir la stratégie dans une mesure limitée en autorisant les origines sécurisées à partir desquelles les scripts doivent être acceptés. Vérifiez que les ressources d’exécution chargées avec des autorisations élevées d’une extension sont exactement les ressources attendues et ne sont pas remplacées par un attaquant réseau actif. Comme les attaques de l’intercepteur sont à la fois triviales et indétectables sur HTTP, ces origines ne sont pas acceptées.

Actuellement, vous pouvez autoriser les origines qui ont les schémas suivants : blob, filesystem, httpset extension. La partie hôte de l’origine doit être spécifiée explicitement pour les https schémas et extension . Les caractères génériques tels que https :, https://* et https://*.com ne sont pas autorisés ; les caractères génériques de sous-domaine tels que https://*.example.com sont autorisés. Les domaines de la liste Suffixe public sont également vus comme des domaines génériques de niveau supérieur. Pour charger une ressource à partir de ces domaines, le sous-domaine doit être répertorié explicitement. Par exemple, https://*.cloudfront.net n’est pas valide, mais https://XXXX.cloudfront.net et https://*.XXXX.cloudfront.net peut être allowlisted.

Pour faciliter le développement, les ressources chargées via HTTP à partir de serveurs sur votre ordinateur local peuvent être allowlisted. Vous pouvez autoriser les sources de script et d’objet sur n’importe quel port de http://127.0.0.1 ou http://localhost.

Remarque

La restriction par rapport aux ressources chargées sur HTTP s’applique uniquement aux ressources qui sont directement exécutées. Vous êtes toujours libre, par exemple, d’établir XMLHTTPRequest des connexions à n’importe quelle origine de votre choix ; la stratégie par défaut ne restreint connect-src ni l’une des autres directives CSP de quelque manière que ce soit.

Une définition de stratégie souple qui permet de charger des ressources de script à partir de example.com https peut ressembler à ceci :

"content_security_policy": "script-src 'self' https://example.com; object-src 'self'"

Remarque

et object-src sont tous deux script-src définis par la stratégie. Microsoft Edge n’accepte pas une stratégie qui ne limite pas chacune de ces valeurs à (au moins) «self ».

JavaScript évalué

La stratégie par rapport eval() à et les fonctions associées telles que setTimeout(String), setInterval(String)et new Function(String) peuvent être assouplies en ajoutant unsafe-eval à votre stratégie :

"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"

Toutefois, vous devez éviter d’assouplir les stratégies. Ces types de fonctions sont des vecteurs d’attaque XSS notoires.

Renforcement de la stratégie par défaut

Vous pouvez renforcer cette politique dans la mesure où votre extension le permet, afin d’accroître la sécurité, au détriment de la commodité. Pour spécifier que votre extension peut uniquement charger des ressources de n’importe quel type (images, etc.) à partir du package d’extension associé, par exemple, une stratégie de default-src 'self' peut être appropriée.

Scripts de contenu

La stratégie en cours s’applique aux pages d’arrière-plan et aux pages d’événements de l’extension. La façon dont les scripts de contenu s’appliquent aux scripts de contenu de l’extension est plus complexe.

Les scripts de contenu ne sont généralement pas soumis au csp de l’extension. Étant donné que les scripts de contenu ne sont pas html, l’impact main de cela est qu’ils peuvent utiliser eval même si le fournisseur de solutions Cloud de l’extension ne spécifie unsafe-evalpas , bien que cela ne soit pas recommandé. En outre, le csp de la page ne s’applique pas aux scripts de contenu. Les balises que les scripts de contenu créent et placent dans le DOM de la page sur laquelle ils s’exécutent sont plus complexes <script> . Ceux-ci sont référencés en tant que scripts injectés DOM à l’avenir.

Les scripts injectés dom qui s’exécutent immédiatement après l’injection dans la page s’exécutent comme prévu. Imaginez un script de contenu avec le code suivant comme exemple simple :

document.write("<script>alert(1);</script>");

Ce script de contenu provoque un alert immédiatement sur le document.write(). Notez que cela s’exécute quelle que soit la stratégie spécifiée par une page. Toutefois, le comportement devient plus compliqué à la fois à l’intérieur de ce script injecté DOM et pour tout script qui ne s’exécute pas immédiatement lors de l’injection.

Imaginez que votre extension s’exécute sur une page qui fournit un fournisseur de services de configuration associé qui spécifie script-src 'self'. Imaginez maintenant que le script de contenu exécute le code suivant :

document.write("<button onclick='alert(1);'>click me</button>'");

Si un utilisateur clique sur ce bouton, le onclick script ne s’exécute pas. Cela est dû au fait que le script n’a pas été exécuté immédiatement et que le code qui n’est pas interprété tant que l’événement click ne se produit pas n’est pas considéré comme faisant partie du script de contenu, de sorte que le csp de la page (et non de l’extension) limite le comportement. Et étant donné que ce fournisseur csp ne spécifie unsafe-inlinepas , le gestionnaire d’événements inline est bloqué.

La bonne façon d’implémenter le comportement souhaité dans ce cas consiste à ajouter le onclick gestionnaire en tant que fonction à partir du script de contenu, comme suit :

document.write("<button id='mybutton'>click me</button>'");
var button = document.getElementById('mybutton');
button.onclick = function() {
      alert(1);
};

Un autre problème similaire se produit si le script de contenu exécute ce qui suit :

var script = document.createElement('script');
script.innerHTML = 'alert(1);'
document.getElementById('body').appendChild(script);

Dans ce cas, le script s’exécute et l’alerte s’affiche. Toutefois, considérez le cas suivant :

var script = document.createElement('script');
script.innerHTML = 'eval("alert(1);")';
=document.getElementById('body').appendChild(script);

Pendant l’exécution du script initial, l’appel à eval est bloqué. Autrement dit, bien que le runtime de script initial soit autorisé, le comportement dans le script est réglementé par le fournisseur de solutions Cloud de la page. Par conséquent, selon la façon dont vous écrivez des scripts injectés dom dans votre extension, les modifications apportées au fournisseur de solutions cloud de la page peuvent affecter le comportement de votre extension.

Étant donné que les scripts de contenu ne sont pas affectés par le fournisseur de solutions Cloud de la page, c’est une excellente raison de placer autant de comportement que possible de votre extension dans le script de contenu, plutôt que des scripts injectés dom.

Voir aussi

Remarque

Les parties de cette page sont des modifications basées sur le travail créé et partagé par Google et utilisées conformément aux termes décrits dans la licence internationale Creative Commons Attribution 4.0. La page d’origine se trouve ici.

Licence Creative Commons Cette œuvre est concédée sous licence creative commons attribution 4.0 international.