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中,此解压扩展无法加载,显示错误:
如果我将'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文件中。
答案 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>
我还测试了将适用的指令放在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>
以下是生成哈希的两种方法:
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))
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)
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指的是此问题。