【问题标题】:Chrome version 18+: How to allow inline scripting with a Content Security Policy?Chrome 版本 18+:如何使用内容安全策略允许内联脚本?
【发布时间】:2012-01-20 02:22:54
【问题描述】:

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

我正在尝试让 CSP 用于内联脚本,但我不知道我做错了什么,或者这是否是 Chrome 18 的错误。

ma​​nifest.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 中,这个解压后的扩展加载失败,显示错误:

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

因为 Content-Security-Policy 拒绝执行内联脚本。

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

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


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

【问题讨论】:

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


【解决方案1】:

对于最新版本的 Chrome (46+),之前接受的答案不再正确。 unsafe-inline 仍然没有效果(在清单和meta 标头标签中),但根据documentation,您可以使用here 描述的技术来放松限制。

&lt;script&gt; 元素的哈希用法

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

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

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

示例

考虑以下几点:

ma​​nifest.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>

结果

进一步调查

我还测试了将适用的指令放在 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>

结果

附录:生成哈希

这里有两种生成哈希的方法:

  1. Python(将 JS 传递到标准输入,将其通过管道传递到其他地方):
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:
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插件。

【讨论】:

  • 你如何从url 获取 SHA256 Base 64 字符串?试图从中制作一个 js 文件,但生成的 SHA 不起作用。
  • 您可以使用此service 从 url 中获取 Base64 SHA256 字符串。
  • @Stanislasdrg 我添加了有关生成哈希的其他信息。
  • 我得到了 'content_security_policy':必须指定 CSP 指令 'object-src'(显式地或通过 'default-src' 隐式地指定)并且必须仅将安全资源列入白名单。
  • @ChrisHunt 以后,请在提及另一个答案时删除一个链接。我试图在此处更新第一句话,但我不确定您发布此答案时哪个答案是“当前”。
【解决方案2】:

以下答案适用于旧版 Chrome (https://stackoverflow.com/a/38554505/422670

我刚刚为https://stackoverflow.com/a/11670319/422670这个问题发布了一个非常相似的答案

如前所述,there's no way to relax the inline security policy in v2 extensionsunsafe-inline 根本不起作用,故意的。

除了将所有 javascript 移动到 js 文件中并使用 &lt;script src&gt; 指向它们之外,真的没有其他方法。

不过,可以选择在沙盒 iframe 中执行 Eval 和 new Function,例如清单中的以下行:

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

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

现在,Google Chrome 团队在 github eval in iframe 上提供了一个完整示例,说明如何通过与沙盒 iframe 以及 short analytics tutorial 通信来规避问题

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

编辑

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

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

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

这出现在trunk documentation 并在线程"eval re-allowed" 中讨论

inline scripts 不会回来了:

没有机制可以放宽对执行内联 JavaScript 的限制。特别是,设置包含'unsafe-inline' 的脚本策略将无效。

【讨论】:

  • @Derek 我知道!!但有些事情可能会发生变化,交叉手指。刚刚更新了我的答案:)
  • 但是他们仍然不让我们使用内联脚本...There is no mechanism for relaxing the restriction against executing inline JavaScript.
  • @Derek 你是正确的内联脚本,但我想我会用即将到来的新闻更新我的答案,我只是编辑得更准确,谢谢!
  • 此答案不再适用,请参阅我的评论以及更新状态here
  • @Stefano 我在仅通过 http 提供服务的 chrome 扩展中使用 Loklak API。我面临同样的错误Content Security Policy。你能告诉我如何解决这个问题吗? API示例链接:loklak.org/api/search.json?q=from%3Atwitter 整个错误是:Refused to load the script 'http://loklak.org/api/search.json?callback=loklakFetcher.handleData&amp;q=muanchiou&amp;count=25&amp;source=cache&amp;fields=&amp;limit=&amp;timezoneOffset=60&amp;minified=true' because it violates the following Content Security Policy directive: "script-src 'self'".
【解决方案3】:

Hash usage for inline scripts 在内容安全策略级别 2 中是允许的。从规范中的示例来看:

内容安全策略: script-src 'sha512-YWIzOWNiNzJjNDRlYzc4MTgwMDhmZDlkOWI0NTAyMjgyY2MyMWJlMWUyNjc1ODJlYWJhNjU5MGU4NmZmNGU3OAo='

另一种选择是nonce,同样来自示例:

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

然后

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

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

【讨论】:

  • 但这在 Chrome extensions 中真的有效吗?你可以添加一个例子吗?因为the docs are quite clear“没有机制可以放宽对执行内联 JavaScript 的限制。”
  • @Xan 你必须试验才能确定;文档可能已过时,因为它们似乎仅引用 CSP 级别 1。无论如何,如果有办法规避对内联脚本的禁令,几乎可以肯定是使用哈希或来自 CSP 的 nonce 2 级。
  • 扩展不盲目实现规范;只允许一些事情。所以我非常怀疑你的观察是否相关,除非有样本可以证明。
  • @Xan:当前读取并出现在搜索结果中的问题不仅限于扩展名。也许这对于遇到此主题的其他人可能是有用的信息。
  • 那么标题需要更新。您可以从问题中看到,它专门针对 Chrome 扩展程序的更改,将内容安全策略设置添加到清单并收紧了默认设置。
【解决方案4】:

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 指的是这个问题。

【讨论】:

  • 原来这不是错误,而是一种新的安全措施。从第二个链接中的反馈确认。那里还有其他有用的信息/示例。
猜你喜欢
  • 1970-01-01
  • 2016-06-28
  • 2019-04-06
  • 1970-01-01
  • 1970-01-01
  • 2021-03-25
  • 2019-08-10
  • 2017-06-16
  • 2023-02-09
相关资源
最近更新 更多