我在 ASP.NET MVC 4 中开发了 MVC 应用程序。我在几个页面中使用了 javascript。一些 javascript 被引用为
@Scripts.Render("~/Scripts/bootstrap")
@Scripts.Render("~/Scripts/js")
还有一些内联脚本,例如
<script type="javascript">
// javascript code
</script>
我想为此网站实施内容安全策略。该站点托管在 IIS 中。因此,在 IIS 中,我在 HTTP 响应标头中添加 content-security-policy 标头为
object-src 'none';
script-src 'nonce-{random}' 'unsafe-inline' 'unsafe-eval' 'strict-dynamic' https: http:;
base-uri 'self';
report-uri https://csp.withgoogle.com/csp/<unique_id>/<application_version>
因此每个响应都将包含此标头。
问题:
插入随机数标签,尤其是在 CSP 中将它们匹配通常很棘手。如果您的脚本代码是静态的并且不包含任何更改,那么根据哈希值将它们列入白名单会更容易。如果您删除“不安全内联”,许多浏览器会告诉您需要添加哪些哈希值。
请注意,您的 script-src 包括 https: 和 http: 将允许它加载 http 和 https 上的任何脚本。如果您的页面通过 https 提供服务,则将不允许活动混合内容,并且 http 上的脚本将不会加载。
使用 OWIN 中间件,您可以在 ASP.NET MVC 5 中轻松注入标头。设置 OWIN 启动后(请参阅 https://learn.microsoft.com/en-us/aspnet/aspnet/overview/owin -and-katana/owin-startup-class-detection)您可以将此代码添加到启动中以生成动态 CSP 标头:
我使用
RandomNumberGenerator
而不是 RNGCryptoServiceProvider
更新了下面的代码,因为后者已被 Microsoft 标记为已过时:
public void Configuration(IAppBuilder app)
{
app.Use((context, next) =>
{
string nonce = null;
using (var rng = RandomNumberGenerator.Create()) {
var nonceBytes = new byte[32];
rng.GetBytes(nonceBytes);
nonce = Convert.ToBase64String(nonceBytes);
}
context.Set("ScriptNonce", nonce);
context.Response.Headers.Add("Content-Security-Policy",
new[] {string.Format("script-src 'self' 'nonce-{0}'", nonce)});
return next();
});
//Other configuration...
}
然后您可以添加以下 HTML 帮助器以在您的 razor 视图中使用它:
public static class NonceHelper
{
public static IHtmlString ScriptNonce(this HtmlHelper helper)
{
var owinContext = helper.ViewContext.HttpContext.GetOwinContext();
return new HtmlString(owinContext.Get<string>("ScriptNonce"));
}
}
然后你在你的视图中使用这个助手:
<script type="text/javascript" nonce="@Html.ScriptNonce()">
//my script body
</script>
渲染的结果是这样的:
<script type="text/javascript" nonce="WpvQQK0FO/ZAljsQDGMLEgi2hrvIBVPQNak9zIWqRZE=">
//my script body
</script>
请注意,如果攻击者可以影响脚本元素的主体,则随机数对您没有帮助,而散列可以防止这种情况。然而,哈希值也有其自身的缺点,例如 HTTP 标头的膨胀以及更加脆弱。