Chrome 18+:如何使用内容安全政策允许内联脚本?

时间:2011-12-14 09:41:45

标签: google-chrome google-chrome-extension content-security-policy

Chrome 18 Dev / Canary刚刚发布,某些扩展程序的清单中需要content_security_policy

我正在努力让CSP为内联脚本编写工作,但我不知道我做错了什么或者这是否是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>

在Chrome 18中,此解压扩展无法加载,显示错误:

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

如果我将'unsafe-inline'更改为'self',则扩展程序会正常加载,但alert()不起作用,并且选项页面的控制台包含错误:

  

因内容安全政策而拒绝执行内联脚本。

在Chrome 16中,使用'unsafe-inline'可以使扩展程序正常加载,alert()也能正常工作。但是,在Chrome 16中,将'unsafe-inline'替换为'foo'会让扩展程序加载,但当然不会让alert()工作,所以Chrome 18可能比16更严格,但是...... < / p>

default-src 'unsafe-inline'实际上是无效的,还是这个错误?我可以使用什么CSP值使alert()在Chrome 18中运行?


根据下面接受的答案,内联脚本不再适用于Chrome 18中的扩展程序。alert()需要放在自己的JavaScript文件中。

4 个答案:

答案 0 :(得分:24)

对于最新版本的Chrome(46+),目前的答案已不再适用。 unsafe-inline仍然没有效果(在清单和meta标头标记中),但根据documentation,您可以使用here所述的技术来放宽限制。< / p>

  

<script>元素的哈希用法

     

script-src指令允许开发人员将其哈希指定为允许的脚本源,从而将特定内联脚本列入白名单。

     

用法很简单。服务器计算特定脚本块内容的哈希值,并在Content-Security-Policy头中包含该值的base64编码:

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

实施例

请考虑以下事项:

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>

<强>结果
alert dialog from inline script

进一步调查

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

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>

<强>结果
console error messages about content security policy

附录:生成哈希

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

  1. Python(将JS传递给stdin,将其传送到其他地方):
  2. 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. 在JS中,使用Stanford Javascript Crypto Library
    2. 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);
      }
      

      确保在内联脚本中散列时,包含脚本标记的整个内容(包括所有前导/尾随空格)。如果要将其合并到构建中,可以使用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插件。

答案 1 :(得分:14)

以下答案适用于旧版Chrome(&lt; 46)。对于最近的,请查看@ Chris-Hunt回答https://stackoverflow.com/a/38554505/422670

我刚刚针对问题https://stackoverflow.com/a/11670319/422670

发布了一个非常相似的答案

如上所述, there's no way to relax the inline security policy in v2 extensions unsafe-inline故意无效。

除了将所有javascript移动到js文件中并使用<script src>指向它们之外别无他法。

但是,可以选择在沙盒iframe中执行Eval和new Function,例如在清单中使用以下行:

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

沙盒页面无法访问扩展程序或应用程序API,也无法直接访问非沙盒页面(它可以通过postMessage()与它们通信)。您可以使用特定CSP进一步限制沙盒权限

现在,github eval in iframe上的Google Chrome小组就如何通过与沙盒iframe进行通信来解决问题以及short analytics tutorial

提供了一个完整的示例

感谢Google,在阵容中有很多扩展名重写:(

修改

可以放宽REMOTE脚本的安全策略。但不适用于内联。

  

通过在您的政策中添加eval(),可以放宽针对setTimeout(String)及其亲属(如setInterval(String)new Function(String)'unsafe-eval'的政策:   "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"

     

但是,我们强烈建议不要这样做。这些函数是臭名昭着的XSS攻击向量。

这出现在trunk documentation中,并在帖子"eval re-allowed"

中讨论

inline scripts不会回来:

  

没有放松对执行内联JavaScript的限制的机制。特别是,设置包含'unsafe-inline'的脚本策略将不起作用。

答案 2 :(得分:3)

内容安全策略级别2中允许

Hash usage for inline scripts。来自规范中的示例:

  

内容安全-政策:   script-src&#39; sha512-YWIzOWNiNzJjNDRlYzc4MTgwMDhmZDlkOWI0NTAyMjgyY2MyMWJlMWUyNjc1ODJlYWJhNjU5MGU4NmZmNGU3OAo =&#39;

另一种选择是nonce,再次来自示例:

  

内容 - 安全 - 政策:script-src&#39; self&#39; &#39; nonce- $ RANDOM&#39 ;;

然后

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

这些似乎在Chrome 40+中受支持,但我不确定目前其他浏览器会有什么运气。

答案 3 :(得分:2)

Afaik,这是一个错误。

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

有效,而

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

犯规。

这真的是前沿技术,请查看http://code.google.com/p/chromium/issues/detail?id=105796了解详细信息。

更新:http://code.google.com/p/chromium/issues/detail?id=107538指的是此问题。