web-dev-qa-db-fra.com

Chrome 18+: comment autoriser les scripts en ligne avec une politique de sécurité du contenu?

Chrome 18 Dev/Canary vient de sortir et content_security_policy sera nécessaire dans le manifeste pour certaines extensions.

J'essaie de faire fonctionner un CSP pour les scripts en ligne, mais je ne sais pas si je fais quelque chose de mal ou s'il s'agit d'un bogue Chrome 18.

manifest.json:

{
    "name": "CSP Test",
    "version": "1.0",
    "manifest_version": 2,
    "options_page": "test.html",
    "content_security_policy": "default-src 'unsafe-inline'"
}

test.html:

<html><head>
<script type="text/javascript">
        alert("hello");
</script>
</head></html>

Dans Chrome 18, cette extension décompressée ne se charge pas, affichant une erreur:

Could not load extension from '[extension directory]'. Invalid value for 'content_security_policy'.

Si je change 'unsafe-inline' En 'self', L'extension se charge correctement, mais alert() ne fonctionne pas et la console de la page d'options contient une erreur:

Refus d'exécuter le script en ligne en raison de Content-Security-Policy.

Dans Chrome 16, l'utilisation de 'unsafe-inline' Permet à l'extension de se charger correctement et alert() fonctionne également. Cependant, dans Chrome 16, remplacer 'unsafe-inline' Par 'foo' Laisse l'extension se charger, mais bien sûr ne laisse pas alert() fonctionner, donc peut-être Chrome 18 est plus stricte que 16, mais ...

default-src 'unsafe-inline' Est-il réellement invalide ou s'agit-il d'un bogue? Quelle valeur CSP puis-je utiliser pour faire fonctionner alert() dans Chrome 18?


Sur la base de la réponse acceptée ci-dessous, les scripts en ligne ne fonctionnent plus dans les extensions de Chrome 18. alert() devra être placé dans son propre fichier JavaScript.

29
Chris McFarland

Pour les versions récentes de Chrome (46+), la réponse actuelle n'est plus vraie. unsafe-inline N'a toujours aucun effet (dans le manifeste et dans les balises d'en-tête meta) ), mais selon la documentation , vous pouvez utiliser la technique décrite ici pour assouplir la restriction.

Utilisation du hachage pour les éléments <script>

La directive script-src Permet aux développeurs de mettre en liste blanche un script en ligne particulier en spécifiant son hachage comme source autorisée de script.

L'utilisation est simple. Le serveur calcule le hachage du contenu d'un bloc de script particulier et inclut l'encodage base64 de cette valeur dans l'en-tête Content-Security-Policy:

Content-Security-Policy: default-src 'self';
                     script-src 'self' https://example.com 'sha256-base64 encoded hash'

Exemple

Considérer ce qui suit:

manifest.json :

{
  "manifest_version": 2,
  "name": "csp test",
  "version": "1.0.0",
  "minimum_chrome_version": "46",
  "content_security_policy": "script-src 'self' 'sha256-WOdSzz11/3cpqOdrm89LBL2UPwEU9EhbDtMy2OciEhs='",
  "background": {
    "page": "background.html"
  }
}

background.html :

<!DOCTYPE html>
<html>
  <head></head>
  <body>
    <script>alert('foo');</script>
  </body>
</html>

Résultat :
alert dialog from inline script

Complément d'enquête

J'ai également testé la mise de la directive applicable dans une balise meta au lieu du manifeste. Alors que le CSP indiqué dans le message de la console incluait le contenu de la balise, il n'exécutait pas le script en ligne (dans Chrome 53).

nouveau background.html :

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'sha256-WOdSzz11/3cpqOdrm89LBL2UPwEU9EhbDtMy2OciEhs='">
  </head>
  <body>
    <script>alert('foo');</script>
  </body>
</html>

Résultat :
console error messages about content security policy

Annexe: Génération des hachages

Voici deux méthodes pour générer les hachages:

  1. Python (passez JS à stdin, redirigez-le ailleurs):
import hashlib
import base64
import sys

def hash(s):
    hash = hashlib.sha256(s.encode()).digest()
    encoded = base64.b64encode(hash)
    return encoded

contents = sys.stdin.read()
print(hash(contents))
  1. Dans JS, en utilisant la Stanford Javascript Crypto Library :
var sjcl = require('sjcl');
// Generate base64-encoded SHA256 for given string.
function hash(s) {
  var hashed = sjcl.hash.sha256.hash(s);
  return sjcl.codec.base64.fromBits(hashed);
}

Assurez-vous lors du hachage des scripts en ligne que le contenu entier de la balise de script est inclus (y compris tous les espaces blancs de début/fin). Si vous souhaitez intégrer cela dans vos builds, vous pouvez utiliser quelque chose comme cheerio pour obtenir les sections pertinentes. De manière générique, pour tout html, vous pouvez faire:

var $ = cheerio.load(html);
var csp_hashes = $('script')
  .map((i, el) => hash($(el).text())
  .toArray()
  .map(h => `'sha256-${h}'`)
  .join(' ');
var content_security_policy = `script-src 'self' 'unsafe-eval' ${csp_hashes}; object-src 'self'`;

Il s'agit de la méthode utilisée dans hash-csp , un plugin gulp pour générer des hachages.

23
Chris Hunt

La réponse suivante est vraie pour les anciennes versions de Chrome (<46). Pour les plus récentes, veuillez vérifier @ Chris-Hunt réponse https : //stackoverflow.com/a/38554505/42267

Je viens de poster une réponse très similaire à la question https://stackoverflow.com/a/11670319/42267

Comme cela est dit, il n'y a aucun moyen d'assouplir la politique de sécurité en ligne dans les extensions v2. unsafe-inline Ne fonctionne tout simplement pas, intentionnellement.

Il n'y a vraiment pas d'autre moyen que de déplacer tout votre javascript dans des fichiers js et de les pointer avec un <script src>.

Il y a cependant la possibilité de faire Eval et new Function dans un iframe en bac à sable, par exemple avec les lignes suivantes dans le manifeste:

"sandbox": {
    "pages": [
      "page1.html",
      "directory/page2.html"
    ]
},

Une page en bac à sable n'aura pas accès aux extensions ou aux API d'application, ni à un accès direct aux pages non en bac à sable (elle peut communiquer avec elles via postMessage ()). Vous pouvez restreindre davantage les droits du bac à sable avec un CSP spécifique

Il y a maintenant un exemple complet de Google Chrome team sur le github eval in iframe sur la façon de contourner le problème en communiquant avec un iframe en bac à sable, ainsi qu'un - court tutoriel d'analyse

Merci à Google, il y a beaucoup de réécriture d'extensions dans la gamme :(

[~ # ~] modifier [~ # ~]

Il est possible d'assouplir la politique de sécurité pour les scripts REMOTE. Mais pas pour les inlines.

La politique contre eval() et ses parents comme setTimeout(String), setInterval(String) et new Function(String) peut être assouplie en ajoutant 'unsafe-eval' À votre politique: "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"

Cependant, nous vous déconseillons fortement de le faire. Ces fonctions sont des vecteurs d'attaque XSS notoires.

cela est apparu dans la documentation du tronc et est discuté dans le fil "eval re-allowed"

inline scripts Ne sera cependant pas de retour:

Il n'existe aucun mécanisme pour assouplir la restriction à l'exécution de JavaScript en ligne. En particulier, la définition d'une stratégie de script incluant 'unsafe-inline' N'aura aucun effet.

14
Stefano

tilisation de hachage pour les scripts en ligne est autorisé dans la politique de sécurité du contenu de niveau 2. De l'exemple de la spécification:

Content-Security-Policy: script-src 'sha512-YWIzOWNiNzJjNDRlYzc4MTgwMDhmZDlkOWI0NTAyMjgyY2MyMWJlMWUyNjc1ODJlYWJhNjU5MGU4NmZmNGU3OAo ='

Une alternative est le nonce , encore une fois à partir des exemples:

Content-Security-Policy: script-src 'self' 'nonce- $ RANDOM';

puis

<script nonce="$RANDOM">...</script>
<script nonce="$RANDOM" src='save-because-nonce'></script>

Ceux-ci semblent pris en charge dans Chrome 40+, mais je ne sais pas quelle chance on aurait avec d'autres navigateurs pour le moment.

3
Brian M. Hunt

Afaik, c'est un bug.

"default-src 'self' https://ssl.google-analytics.com"

fonctionne, tandis que

"default-src 'self' http://ssl.google-analytics.com"

ne fonctionne pas.

C'est vraiment la technologie Edge qui saigne, vérifiez http://code.google.com/p/chromium/issues/detail?id=105796 pour plus de détails.

Mise à jour: http://code.google.com/p/chromium/issues/detail?id=107538 fait référence à ce problème.

2
Maximilian Hils