深度求索:免费API如何助力技术突破
.NET 内容安全策略指南:是什么及如何启用
威胁日益丰富和复杂。为了减轻这些威胁的影响,软件公司不断采用更复杂、更强大的解决方案。
作为开发人员,我们有责任确保利用这些解决方案,调整我们的软件以符合政策,并实施必要的措施。
其中一项措施被称为内容安全策略(CSP)。
本文的目的是帮助人们揭开内容安全概念的神秘面纱。
在本文中,我们将
- 简单定义一下 CSP 是什么,
- 说明如何在我们的平台中启用 CSP,
- 探讨你在此过程中可能遇到的一些问题,以及如何解决这些问题。
注意:本文针对的是 .NET 开发人员。
什么是内容安全策略?
简而言之,CSP 是浏览器在请求网页时强制执行的策略或指令的集合。
在加载页面的过程中,浏览器必须请求并呈现大量内容和代码才能显示页面。
此过程是标准的,并且考虑到所有现代网站都很复杂且由大量 HTML、CSS、JavaScript 以及代码引用的其他资源(如图像和文件)组成,因此完全可以预料到。
具体来说,这个引用的代码可能来自同一来源(请求的域)或其他来源;浏览器不会区分。
一旦执行此代码,浏览器必须处理和执行这些资源,而不能包含任何恶意代码或访问不属于相关网站的数据。
为了在此过程中提供安全性,服务器通过响应头提供了 CSP,以确保浏览器只执行有效的资源。
该安全层通过提供受信任资源的允许列表,帮助缓解攻击者利用跨站点脚本和注入攻击等漏洞。
CSP 示例
让我们看看内容安全策略标头是什么样的:
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'; font-src 'self'; img-src 'self'; frame-src 'self';
请注意,标题中的每个部分都与特定类型的资源相关。
此外,默认的“self”指令规定浏览器必须仅执行来自同一来源的资源。
请注意,您可以通过将资源的 URL 放在“self”旁边来指定您想要从中检索资源的域。
最后,您可以通过设置“*”来允许所有域(除非绝对必要,否则不要这样做)。
启用 CSP
现在我们知道了 CSP 是什么,也看到了它的样子,让我们将它实现到我们的代码中。
要在 ASP.NET core 中实现简单的 CSP 策略,我们只需要在Startup.cs文件中的Configure()方法中的UseEndpoints方法之前添加以下代码。
app.Use(async (context, next) => {
context.Response.Headers.Add("Content-Security-Policy", "default-src 'self'; script-src 'self'; style-src 'self'; font-src 'self'; img-src 'self'; frame-src 'self'");
await next();
});
此代码本质上创建了一个中间件,将 CSP 标头添加到来自我们服务器的所有响应中。
现在您可以检查所有响应标头是否包含上面提到的 CSP 配置(如果之前没有的话)。
浏览器将强制执行任何更改,很可能会破坏您的页面并显示许多警报。
实施适当的内容安全政策需要进行大量修改和适当测试,这需要一些时间。因此,现在,让我们在网站正常运行的同时解决眼前的错误。
为此,我们将使用Content-Security-Policy-Report-Only指令。只需将代码更改为以下内容:
app.Use(async (context, next) => {
context.Response.Headers.Add("Content-Security-Policy-Report-Only", "default-src 'self'; script-src 'self'; style-src 'self'; font-src 'self'; img-src 'self'; frame-src 'self'");
await next();
});
使用“仅报告”会使浏览器不再强制执行指令,但显示相应的违规警报。
这种行为对于平台安全性不重要的开发环境很有帮助,但开发人员需要了解任何违规行为才能充分解决。
处理 CSP 错误
我们知道,在浏览器开发者控制台中看到所有这些警报可能会令人感到害怕。但别担心。一旦您了解了浏览器告诉您的内容,解决这些错误就非常简单了。
开发者控制台报告将指导您改进政策指令并进行必要的更新。
我们的第一步应该是确认浏览器报告的资源确实合法并且对于应用程序的正常运行是必要的。
例如,我们可以看到我们的应用程序正在请求以下内容:
- https://code.jquery.com/jquery-3.5.1.min.js
- https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js
- https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.31/moment-timezone-with-data.js
- https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js
- https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.bundle.min.js
- https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js
- https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css
- https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css
- https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/webfonts/fa-brands-400.woff2
- https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/webfonts/fa-brands-400.woff
- https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/webfonts/fa-brands-400.ttf
- https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/webfonts/fa-regular-400.woff2
- https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/webfonts/fa-regular-400.woff
- https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/webfonts/fa-regular-400.ttf
- https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/webfonts/fa-solid-900.woff2
- https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/webfonts/fa-solid-900.woff
- https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/webfonts/fa-solid-900.ttf
当然,所有这些都是来自可信来源的有效资源。
获得资源列表后,您可以按照如下方式将它们添加到每个相应来源的允许列表中:
app.Use(async (context, next) => {
context.Response.Headers.Add("Content-Security-Policy-Report-Only", "default-src 'self'; script-src 'self' https://code.jquery.com/jquery-3.5.1.min.js https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.31/moment-timezone-with-data.js https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.bundle.min.js https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js; style-src 'self' https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css; font-src 'self' https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/webfonts/fa-brands-400.woff2 https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/webfonts/fa-brands-400.woff https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/webfonts/fa-brands-400.ttf https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/webfonts/fa-regular-400.woff2 https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/webfonts/fa-regular-400.woff https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/webfonts/fa-regular-400.ttf https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/webfonts/fa-solid-900.woff2 https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/webfonts/fa-solid-900.woff https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/webfonts/fa-solid-900.ttf; img-src 'self'; frame-src 'self'");
await next();
});
这样做之后,大多数警报就会消失。
此外,如果您想启用来自特定域的所有资源,您可以通过在指令中指定域来实现。
app.Use(async (context, next) => {
context.Response.Headers.Add("Content-Security-Policy-Report-Only", "default-src 'self'; script-src 'self' https://code.jquery.com https://cdnjs.cloudflare.com https://stackpath.bootstrapcdn.com https://cdn.jsdelivr.net; style-src 'self' https://stackpath.bootstrapcdn.com https://cdnjs.cloudflare.com; font-src 'self' https://cdnjs.cloudflare.com; img-src 'self'; frame-src 'self'");
await next();
});
在线违规
现在,我们的 HTML 中的内联代码怎么样?
嗯,我们可以采取一些措施来解决这些违规行为。
第一种(推荐)方法是将所有内联代码和样式移动到单独的文件并引用它。
这样,您可以确保应用程序的安全性并保持其一致性。
但是,如果您的情况无法做到这一点,您可以将代码移动到<script/>或<style/>标签,并使用 SHA 哈希键来告诉浏览器此标签中的代码是允许的。
您可以使用 SHA256 算法对标签内的代码进行哈希处理来生成哈希键。方便的是,浏览器已经在警报本身中计算了此哈希值,因此您可以轻松地将其添加到指令中。
app.Use(async (context, next) => {
context.Response.Headers.Add("Content-Security-Policy-Report-Only", "default-src 'self'; script-src 'self' https://code.jquery.com https://cdnjs.cloudflare.com https://stackpath.bootstrapcdn.com https://cdn.jsdelivr.net; style-src 'self' https://stackpath.bootstrapcdn.com https://cdnjs.cloudflare.com; font-src 'self' https://cdnjs.cloudflare.com; img-src 'self'; frame-src 'self'");
await next();
});
此外,如果您不想使用 SHA 哈希,您可以使用所谓的“nonce”标签属性并将其添加到相应的标签中。
该解决方案本质上具有相同的目的,但必须使用一些服务器端代码来更新每个请求。
最后,一旦所有更改完成,请记住更新指令并删除生产中的“仅报告”。
确保内容安全
构建强大且安全的网络平台需要广泛的开发、基础设施和安全基础知识。
保护我们的应用程序可能是一个非常复杂且漫长的过程。我们很容易迷失在文章和论坛的迷宫中。尽管如此,我们必须尽可能多地解决安全问题和漏洞。
此外,确保我们平台的弹性和用户信息的安全是一个关键问题,而且随着时间的推移变得越来越复杂。
.NET 是一个强大而直接的平台,可用于构建强大而灵活的 Web 应用程序。此外,它使防范 CSP 漏洞的工作变得非常清晰;无需摆弄复杂的配置或危险的设置。
文章来源:.NET Content Security Policy Guide: What It Is and How to Enable It