Chrome版本18+:如何使用内容安全政策允许内联脚本编写? [英] Chrome version 18+: How to allow inline scripting with a Content Security Policy?

查看:123
本文介绍了Chrome版本18+:如何使用内容安全政策允许内联脚本编写?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Chrome 18 Dev / Canary刚刚发布,并且,您可以使用



进一步调查



我还测试了将适用的指令放在 meta 标记而不是清单。尽管控制台消息中指示的CSP确实包含了标记的内容,但它不会执行内联脚本(在Chrome 53中)。



新的背景。 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>

结果



附录:生成哈希值



以下是两种生成方法哈希值:


  1. Python(将JS传递到stdin,将其通过管道传递到其他地方):



 导入hashlib 
导入base64
导入sys

def hash(s):
hash = hashlib.sha256(s.encode())。digest()
编码= base64.b64encode(hash)
返回编码的

content = sys.stdin.read()
print(hash(contents))




  1. 在JS中,使用斯坦福Javascript加密库



  var sjcl = require(’sjcl'); 
//为给定的字符串生成base64编码的SHA256。
函数哈希值{
var hashed = sjcl.hash.sha256.hash;
return sjcl.codec.base64.fromBits(哈希);
}

在对内联脚本进行哈希处理时,请确保整个包括了脚本标签的内容(包括所有前导/尾随空格)。如果要将其合并到构建中,则可以使用 cheerio 之类的内容。通常,对于任何 html ,您都可以这样做:

  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'`;

这是 hash-csp ,用于生成哈希的gulp插件。


Chrome 18 Dev/Canary has just been released, and content_security_policy will be needed in the manifest for certain extensions.

I'm trying to get a CSP working for inline scripting, but I don't know if I'm doing something wrong or if this is a Chrome 18 bug.

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>

In Chrome 18, this unpacked extension fails to load, displaying an error:

If I change 'unsafe-inline' to 'self', the extension loads fine, but alert() does not work, and the option page's console contains an error:

Refused to execute inline script because of Content-Security-Policy.

In Chrome 16, using 'unsafe-inline' lets the extension load fine and alert() works, too. However, in Chrome 16, replacing 'unsafe-inline' with 'foo' lets the extension load, but of course does not let alert() work, so perhaps Chrome 18 is stricter than 16, but...

Is default-src 'unsafe-inline' actually invalid, or is this a bug? What CSP value can I use to make alert() work in Chrome 18?


Based on the accepted answer below, inline scripts no longer work in extensions in Chrome 18. alert() will need to be placed in its own JavaScript file.

解决方案

For recent versions of Chrome (46+) the current answer is no longer true. unsafe-inline still has no effect (in the manifest and in meta header tags), but per the documentation, you can use the technique described here to relax the restriction.

Hash usage for <script> elements

The script-src directive lets developers whitelist a particular inline script by specifying its hash as an allowed source of script.

Usage is straightforward. The server computes the hash of a particular script block’s contents, and includes the base64 encoding of that value in the Content-Security-Policy header:

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

Example

Consider the following:

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>

Result:

Further investigation

I also tested putting the applicable directive in a meta tag instead of the manifest. While the CSP indicated in the console message did include the content of the tag, it would not execute the inline script (in Chrome 53).

new 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>

Result:

Appendix: Generating the hashes

Here are two methods for generating the hashes:

  1. Python (pass JS to stdin, pipe it somewhere else):

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. In JS, using the 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);
}

Make sure when hashing the inline scripts that the whole contents of the script tag are included (including all leading/trailing whitespace). If you want to incorporate this into your builds, you can use something like cheerio to get the relevant sections. Generically, for any html, you can do:

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'`;

This is the method used in hash-csp, a gulp plugin for generating hashes.

这篇关于Chrome版本18+:如何使用内容安全政策允许内联脚本编写?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆