安全 HTTP 响应头
默认的安全头
Spring Security 提供了一组默认的安全相关的 HTTP 响应头,以提供安全的默认设置。
Spring Security 的默认设置是包含以下头部:
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-Frame-Options: DENY
X-XSS-Protection: 0
Strict-Transport-Security 仅在 HTTPS 请求中添加
如果默认设置不能满足您的需求,您可以轻松地从这些默认设置中移除、修改或添加头部。有关每个头部的更多详细信息,请参阅相应的部分:
缓存控制
Spring Security 的默认设置是禁用缓存,以保护用户的内容。
如果用户认证后查看敏感信息,然后注销,我们不希望恶意用户能够通过点击返回按钮来查看这些敏感信息。默认发送的缓存控制标头是:
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
为了默认安全,Spring Security 默认会添加这些头部。然而,如果你的应用程序提供了自己的缓存控制头部,Spring Security 将不会进行干涉。这允许应用程序确保静态资源(如 CSS 和 JavaScript)可以被缓存。
Content-Type Options
历史上,包括 Internet Explorer 在内的浏览器会尝试通过使用内容嗅探来猜测请求的内容类型。这使得浏览器能够通过猜测未指定内容类型的资源的内容类型来改善用户体验。例如,如果浏览器遇到一个未指定内容类型的 JavaScript 文件,它就能够猜测内容类型并运行它。
在允许上传内容时,还应该做许多其他事情(例如仅在特定域中显示文档、确保设置了 Content-Type 标头、清理文档等)。然而,这些措施超出了 Spring Security 所提供的范围。还需要指出的是,当禁用内容嗅探时,必须指定内容类型才能使一切正常工作。
内容嗅探的问题在于,这允许恶意用户使用多态文件(即,作为多种内容类型的合法文件)来执行 XSS 攻击。例如,某些网站可能允许用户向网站提交一个有效的 PostScript 文档并查看它。恶意用户可能会创建一个既是有效 PostScript 文档又是有效 JavaScript 文件的文档,并用它来执行 XSS 攻击。
默认情况下,Spring Security 通过向 HTTP 响应添加以下头部来禁用内容嗅探:
X-Content-Type-Options: nosniff
HTTP 严格传输安全 (HSTS)
当你输入银行的网站时,你是输入 mybank.example.com
还是输入 https://mybank.example.com
?如果你省略了 https
协议,你可能会受到中间人攻击。即使网站执行重定向到 https://mybank.example.com
,恶意用户也可能会拦截初始的 HTTP 请求并操纵响应(例如,重定向到 https://mibank.example.com
并窃取其凭证)。
许多用户会省略 https
协议,这也是创建HTTP 严格传输安全 (HSTS)的原因。一旦将 mybank.example.com
添加为 HSTS 主机,浏览器就可以预先知道任何对 mybank.example.com 的请求都应该被解释为 https://mybank.example.com
。这大大减少了中间人攻击发生的可能性。
根据 RFC6797,HSTS 头仅注入到 HTTPS 响应中。要使浏览器认可该头,浏览器必须首先信任签署用于建立连接的 SSL 证书的 CA(而不仅仅是 SSL 证书)。
一种将站点标记为HSTS主机的方法是将主机预加载到浏览器中。另一种方法是在响应中添加Strict-Transport-Security
头。例如,Spring Security的默认行为是添加以下头信息,指示浏览器在一年内(非闰年有31536000秒)将该域视为HSTS主机:
Strict-Transport-Security: max-age=31536000 ; includeSubDomains ; preload
可选的 includeSubDomains
指令指示浏览器,子域名(如 secure.mybank.example.com
)也应被视为 HSTS 域。
可选的 preload
指令指示浏览器应将该域预加载为 HSTS 域。有关 HSTS 预加载的更多详细信息,请参阅 hstspreload.org。
HTTP 公钥固定 (HPKP)
为了保持被动,Spring Security 仍然在 servlet 环境中提供了对 HPKP 的支持(参见此处)。然而,由于前面列出的原因,Spring Security 团队不再推荐使用 HPKP。
HTTP 公钥固定 (HPKP) 向 Web 客户端指定与特定 Web 服务器一起使用的公钥,以防止使用伪造证书进行中间人 (MITM) 攻击。如果使用正确,HPKP 可以增加对被破坏的证书的额外保护层。然而,由于 HPKP 的复杂性,许多专家不再推荐使用它,并且 Chrome 甚至已经移除了对它的支持。
有关为什么不再推荐使用 HPKP 的更多详细信息,请阅读 Is HTTP Public Key Pinning Dead? 和 I’m giving up on HPKP。
X-Frame-Options
让您的网站被添加到框架中可能会导致安全问题。例如,通过使用巧妙的 CSS 样式,用户可能会被诱骗点击他们本无意点击的内容。例如,一个已登录银行账户的用户可能会点击一个允许其他用户访问的按钮。这种攻击被称为 Clickjacking。
另一种现代的应对点击劫持的方法是使用 内容安全策略 (CSP)。
有几种方法可以缓解点击劫持攻击。例如,为了保护旧版浏览器免受点击劫持攻击,你可以使用frame breaking code。虽然不完美,但对于旧版浏览器来说,frame breaking code 是你能做的最好的选择。
一种更现代的解决点击劫持的方法是使用 X-Frame-Options 头。默认情况下,Spring Security 通过使用以下头信息来禁止在 iframe 中渲染页面:
X-Frame-Options: DENY
X-XSS-Protection
一些浏览器内置了过滤反射型 XSS 攻击的功能。该过滤器已在主要浏览器中被弃用,当前的 OWASP 建议是将该头部显式设置为 0。
默认情况下,Spring Security 使用以下标头阻止内容:
X-XSS-Protection: 0
内容安全策略 (CSP)
内容安全策略 (CSP) 是一种 Web 应用程序可以用来缓解内容注入漏洞(如跨站脚本攻击 (XSS))的机制。CSP 是一种声明性策略,它为 Web 应用程序作者提供了一种声明并最终告知客户端(用户代理)Web 应用程序期望从哪些来源加载资源的手段。
内容安全策略(Content Security Policy)并非旨在解决所有内容注入漏洞。相反,您可以使用CSP来帮助减少内容注入攻击造成的危害。作为第一道防线,Web应用程序作者应验证其输入并编码其输出。
一个 Web 应用程序可以通过在响应中包含以下 HTTP 头之一来使用 CSP:
-
Content-Security-Policy
-
Content-Security-Policy-Report-Only
这些标头中的每一个都用作向客户端传递安全策略的机制。安全策略包含一组安全策略指令,每个指令负责声明特定资源表示的限制。
例如,Web 应用程序可以通过在响应中包含以下标头来声明它期望从特定的、受信任的来源加载脚本:
Content-Security-Policy: script-src https://trustedscripts.example.com
尝试从 script-src
指令中声明的来源之外的其他来源加载脚本会被用户代理阻止。此外,如果安全策略中声明了 report-uri 指令,违反行为将由用户代理报告给声明的 URL。
例如,如果一个 Web 应用程序违反了声明的安全策略,下面的响应头会指示用户代理将违规报告发送到策略的 report-uri
指令中指定的 URL。
Content-Security-Policy: script-src https://trustedscripts.example.com; report-uri /csp-report-endpoint/
违规报告 是标准的 JSON 结构,可以通过 Web 应用程序自己的 API 或公开托管的 CSP 违规报告服务(如 report-uri.io/)来捕获。
Content-Security-Policy-Report-Only
标头为 Web 应用程序的作者和管理员提供了监控安全策略的能力,而不是强制执行它们。此标头通常在为站点试验或开发安全策略时使用。当认为某个策略有效时,可以通过使用 Content-Security-Policy
标头字段来强制执行该策略。
根据以下响应头,策略声明脚本可以从两个可能的来源之一加载。
Content-Security-Policy-Report-Only: script-src 'self' https://trustedscripts.example.com; report-uri /csp-report-endpoint/
如果该站点违反此策略,试图从 evil.example.com
加载脚本,用户代理会将违规报告发送到由 report-uri
指令指定的声明 URL,但仍会让违规资源加载。
将内容安全策略应用到 Web 应用程序通常是一项不简单的任务。以下资源可能会在为您的网站开发有效的安全策略时提供进一步的帮助:
引荐来源政策
引用者政策 是 Web 应用程序可以用来管理引用者字段的一种机制,该字段包含用户上次所在的页面。
Spring Security 的方法是使用 Referrer Policy 头,该头提供了不同的策略:
Referrer-Policy: same-origin
Referrer-Policy 响应头指示浏览器让目标知道用户之前所在的来源。
功能策略
功能策略 是一种机制,允许 Web 开发者有选择地启用、禁用和修改浏览器中某些 API 和 Web 功能的行为。
Feature-Policy: geolocation 'self'
通过功能策略(Feature Policy),开发人员可以选择加入一组“策略”,让浏览器在你的网站使用的特定功能上强制执行。这些策略限制了网站可以访问的 API,或者修改浏览器对某些功能的默认行为。
权限策略
Permissions Policy 是一种机制,它允许 Web 开发者选择性地启用、禁用和修改浏览器中某些 API 和 Web 功能的行为。
Permissions-Policy: geolocation=(self)
通过Permissions Policy,开发人员可以为浏览器在其网站上使用的特定功能选择一组“策略”。这些策略限制了网站可以访问的API,或者修改了某些功能的浏览器默认行为。
清除站点数据
Clear Site Data 是一种机制,当 HTTP 响应包含此标头时,可以删除任何浏览器端数据(如 cookies、本地存储等):
Clear-Site-Data: "cache", "cookies", "storage", "executionContexts"
这是一个在登出时执行的不错的清理操作。
自定义标头
请参阅相关章节以了解如何配置基于servlet的应用程序。
Spring Security 有机制可以方便地为应用程序添加更常见的安全头。但是,它也提供了钩子来启用添加自定义头。