我必须添加CSP头到一个网站。问题是,这是一个遗留代码,有很多内联脚本和样式的HTML。我不能使用"不安全的内联",因为目的是实际使网站安全,这个指令在OWASP ZAP工具扫描中给出了危险信号。我可以重构HTML和JS代码在某种程度上,但我有几个问题:
-
我已经尝试了固定的nonce(只是为了POC)和列白名单内联脚本的哈希方式。但是由于所有的HTML都是静态的,我如何为每个请求添加新的nonce到脚本标签(就像nonce的实际情况一样)?
-
在这种情况下,提供所有所需脚本和样式的哈希比nonce更好吗?
-
如果我重构所有HTML的代码,从body标签中删除所有内联脚本,并在head中添加单个脚本标签中的代码,这是否意味着内联脚本被消除?简而言之,它算作内联脚本吗?
- 但是由于所有的HTML都是静态的如何为每个请求添加新的nonce到脚本标记(如nonce的实际情况)?
通常使用'hash value'
,因为每次重新加载页面时,很难动态地将nonce="value"
属性插入脚本和样式标签中。然而,对于Nginx web服务器,有一个使用服务器过滤器(ngx_http_sub_module
或ngx_http_substitutions_filter_module
)的解决方案。
在静态HTML中使用一些"唯一字符串":
<script nonce="@@=AAABBBCCCZZZ=@@"></script>
被服务器的过滤器替换为服务器生成的值($request_id):
location / {
subs_filter @@=AAABBBCCCZZZ=@@ $request_id;
}
但是这些模块可能不是默认内置到Nginx服务器,你必须重新构建服务器。
- 在这种情况下,提供所有所需脚本和样式的哈希值比nonce更好吗?
'hashe-value'
主要用于SPA(单页应用程序),在那里你没有可能刷新nonce
值。但是,当您更改代码并需要用新哈希替换一些哈希时,很难管理带有大量哈希的CSP。
因此,在服务器端呈现的情况下,更经常使用'nonce value'
。此外,'nonce value'
不仅可以用于内联脚本,也可以用于外部脚本。
请参阅下面关于JS框架的评论-这些框架可能与'nonce-value'
或'hash-value'
不兼容。
- 如果我重构所有HTML的代码,从body标签中删除所有内联脚本,并在head中添加单个脚本标签中的代码,这是否意味着内联脚本被消除?
负的。CSP算作内联脚本,不仅<script>
标签,而且内置标签事件处理程序,如<button onClick='...'>
和<a href='void(0)'>
的javascript-navigation类。
还有一些JS框架,如jQuery,需要强制'unsafe-inline'
或'unsafe-eval'
,可能与'nonce-value'
或'hash-value'
不兼容。
jQuery从v3.5.0开始兼容'nonce-value'
。但是,由于动态生成主脚本并将其插入<head>
部分,jQuery很难与'hash-value'
兼容。