Spring Security 之防漏洞攻击

相关文章:

  1. OAuth2的定义和运行流程
  2. Spring Security OAuth实现Gitee快捷登录
  3. Spring Security OAuth实现GitHub快捷登录
  4. Spring Security的过滤器链机制
  5. Spring Security OAuth Client配置加载源码分析
  6. Spring Security内置过滤器详解
  7. 为什么加载了两个OAuth2AuthorizationRequestRedirectFilter分析
  8. Spring Security 自定义授权服务器实践
  9. Spring Security 自定义资源服务器实践
  10. Spring Security 自定义用户信息端点与多种登录方式共存
  11. Spring Security 之密码存储

什么是CSRF攻击

了解CSRF攻击的最好方式是通过一个具体的例子。
假设您的银行网站提供了一个转账页面,允许从当前的登录用户向另一个账户转账,转账单可能如下:
Example 1. 转账表单

<form method="post"
	action="/transfer">
<input type="text"
	name="amount"/>
<input type="text"
	name="routingNumber"/>
<input type="text"
	name="account"/>
<input type="submit"
	value="Transfer"/>
</form>

Http请求如下:

POST /transfer HTTP/1.1
Host: bank.example.com
Cookie: JSESSIONID=randomid
Content-Type: application/x-www-form-urlencoded

amount=100.00&routingNumber=1234&account=9876

现在假设您通过了银行网站的认证,然后不不注销的情况下访问了一个不安全的网站,这个网站包含一个HTML页面,格式如下:
Example 3. 不安全的转账表单

<form method="post"
  action="https://bank.example.com/transfer">
  <input type="hidden"
    name="amount"
    value="100.00"/>
  <input type="hidden"
    name="routingNumber"
    value="evilsRoutingNumber"/>
  <input type="hidden"
    name="account"
    value="evilsAccountNumber"/>
  <input type="submit"
    value="立即赢钱"/>
</form>

在你点击“立即赢钱”按钮后,你已经向恶意用户转账了100元,虽然不安全的网站无法看到你的cookie,但与你银行关联的cookie仍然会随请求一起发送。
并且,这个过程可以使用JavaScript来实现自动化,也就是不需要你点击按钮,也可以实现转账。另外的,当访问一个受XSS攻击的站点时,这种情况也很容易发生。

防范CSRF攻击

Spring 提供了两种方式来防范CSRF攻击:

  • 同步令牌模式
  • session cookie指定 SameSite属性
同步令牌模式

防止CSRF攻击最主要且全面的方法是使用同步令牌模式。这种方式除了每个HTTP请求除了session cookie外,另外在HTTP请求中存在一个随机生成的值,称为CSRF令牌。
当提交HTTP请求时,服务器查找预期的CSRF令牌,并将其与HTTP请求中的CSRF令牌进行比较,如果不匹配,HTTP请求将被拒绝。
使用同步令牌模式修改后的示例如下,表单中存在名为_csrf参数的CSRF令牌。
Example 4.同步令牌表单

<form method="post"
  action="/transfer">
  <input type="hidden"
    name="_csrf"
    value="4bfd1575-3ad1-4d21-96c7-4ef2d9f86721"/>
  <input type="text"
    name="amount"/>
  <input type="text"
    name="routingNumber"/>
  <input type="hidden"
    name="account"/>
  <input type="submit"
    value="Transfer"/>
</form>

相应的HTTP请求转账如下:
Example 5. 同步令牌模式后的请求

POST /transfer HTTP/1.1
Host: bank.example.com
Cookie: JSESSIONID=randomid
Content-Type: application/x-www-form-urlencoded

amount=100.00&routingNumber=1234&account=9876&_csrf=4bfd1575-3ad1-4d21-96c7-4ef2d9f86721
SameSite属性

另一种防止CSRF攻击的方式是在cookie上指定SameSite属性。服务器可以在设置cookie时指定SameSite属性,以表示cookie不应该发送到外部站点。

ℹ️ Spring Security 不直接提供cookie的创建,因此不支持SameSite属性的支持。Spring Session 可以在基于servlet的应用程序环境中支持SameSite属性。Spring 框架的 CookieWebSessionIdResolver 为WebFlux应用程序提供开箱即用的SameSite支持。

如果添加了SameSite属性,HTTP头看起来是这个样子:
Example 6. SameSite HTTP response

Set-Cookie: JSESSIONID=randomid; Domain=bank.example.com; Secure; HttpOnly; SameSite=Lax

SameSite属性的有效值为:

  • Strict:设置为该值时,同一站点的所有请求都将包含该Cookie,否则HTTP请求将不包含该Cookie
  • Lax:当请求来自同一站点,或者请求来自top-level navigations(❓不太理解)并且请求是幂等时,将包含该Cookie,否则不包含该Cookie

ℹ️ 可以根据gh-7537 来改进SameSite

要使用SameSite,需要浏览器支持SameSite属性,目前大多数浏览器都支持,但可能老式的浏览器不支持,因此,SameSite建议作为加强防御,而不是唯一的防御方式。

CSRF注意事项

登录

为了防止伪造登录请求,登录HTTP请求应该被保护免受CSRF攻击。防止伪造登录请求,以便恶意用户无法读取受害者的敏感信息。

登出

为了防止伪造注销请求,应保护注销HTTP请求免受CSRF攻击。必须防止伪造注销请求,以便恶意用户无法读取受害者的敏感信息。

ℹ️ 有关攻击的详细描述,可见该博客:Login/logout CSRF: Time to reconsider?

CSRF 和会话超时

通常,预期的CSRF令牌存储在会话中。这意味着一旦会话到期,服务器将找不到预期的CSRF令牌并拒绝HTTP请求。以下是一些解决办法:

  • 减少超时的最佳方法是在表单提交时使用JavaScript请求CSRF令牌。然后使用CSRF令牌更新表单并提交。
  • 另一种选择是使用一些JavaScript,让用户知道会话即将到期。用户可以单击按钮继续并刷新会话。
  • 最后,预期的CSRF令牌可以存储在cookie中。这允许预期的CSRF令牌在会话结束后继续使用。
文件上传

保护multipart请求(文件上传)免受CSRF攻击会导致鸡和蛋的问题。为了防止发生CSRF攻击,必须读取HTTP请求的主体以获取实际的CSRF令牌。然而读取正文意味着文件将被上传,这意味着外部站点可以上传文件。
对于给multipart/form-data请求进行CSRF保护,有两种办法:

  • 在Body中放置CSRF令牌

在请求主体中包含实际的CSRF令牌。通过在Body中放置CSRF令牌,在执行授权之前将读取主体。这意味着任何人都可以在服务器上放置临时文件。但是,只有授权用户才能提交由您的应用程序处理的文件。通常,这是推荐的方法,因为临时文件上载对大多数服务器的影响可以忽略不计。

  • 在URL中放置CSRF令牌

如果允许未经授权的用户上载临时文件是不可接受的,另一种方法是在表单的action属性中包含预期的CSRF令牌作为查询参数。这种方法的缺点是查询参数可能会泄漏。更一般地说,将敏感数据放在正文或标头中以确保其不泄漏被认为是最佳做法。

HiddenHttpMethodFilter

在某些应用程序中,表单参数可用于覆盖HTTP方法。如下,使用delete覆盖了post
Example 10. CSRF Hidden HTTP Method Form

<form action="/process"
  method="post">
  <!-- ... -->
  <input type="hidden"
    name="_method"
    value="delete"/>
</form>

使用该种方式覆盖请求方法,必须将过滤器放置在Spring Security之前执行。

HTTP Headers

有许多HTTP响应头可用于提高web应用程序的安全性。这里专门介绍Spring Security明确支持的各种HTTP响应头。如果需要,还可以配置SpringSecurity来提供自定义头。

Default Security Headers

ℹ️ servlet 和 webflux 应用的详细配置查看对应章节

SpringSecurity提供了一组默认的安全相关HTTP响应头,以提供安全默认值。
Spring Security的默认设置是包含以下headers:
Example 1. 默认的安全HTTP响应头

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: 1; mode=block

ℹ️ 仅在HTTPS请求中添加

如果默认值不满足您的需要,您可以轻松地从这些默认值中删除、修改或添加标题。如下是对每个头的详细介绍。
Cache Control
Spring Security的默认设置是禁用缓存。如果用户通过身份验证查看敏感信息然后注销,我们不希望恶意用户能够单击后退按钮查看敏感信息。默认情况下发送的缓存控制标头为:
Example 2. Default Cache Control HTTP Response Headers

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文件,它将能够猜测内容类型,然后运行它。
内容嗅探的问题在于,这允许恶意用户使用多语言(即,一个对多种内容类型有效的文件)来执行XSS攻击。例如,一些网站可能允许用户向网站提交有效的postscript文档并进行查看。恶意用户可能会创建同时也是有效JavaScript文件的postscript文档,并对其执行XSS攻击。
默认情况下,Spring Security通过向HTTP响应添加以下标头来禁用内容嗅探:
Example 3. nosniff HTTP Response Header

X-Content-Type-Options: nosniff

HTTP Strict Transport Security (HSTS)
如果在访问mybank.example.com地址的时候,省略了https,则有可能会遭到中间人攻击。
如果添加了HSTS 头,那么浏览器将知道任何访问mybank.example.com的地址应该去访问https的地址。这大大降低了遭到中间人攻击的可能性。
将站点标记为HSTS主机的一种方法是将主机预加载到浏览器中。另一种是添加Strict-Transport-Security头到响应头中。例如,Spring Security的默认行为是添加以下标头,指示浏览器在一年内将域视为HSTS主机(一年大约有31536000秒)
Example 4. Strict Transport Security HTTP Response Header

Strict-Transport-Security: max-age=31536000 ; includeSubDomains ; preload

可选的includeSubDomains指令指示浏览器子域(例如secure.mybank.example.com)也应被视为HSTS域。
可选的preload指令指示浏览器域应作为HSTS域在浏览器中预加载。更多信息查看hstspreload.org

HTTP Public Key Pinning (HPKP)

ℹ️ Spring Security仍然在servlet环境中提供对HPKP的支持,但安全团队不再推荐HPKP。

HTTP公钥锁定(HPKP)向web客户端指定与特定web服务器一起使用的公钥,以防止中间人(MITM)使用伪造证书进行攻击。正确使用时,HPKP可以添加额外的保护层,以防止证书受损。然而,由于HPKP的复杂性,许多专家不再推荐使用它,Chrome甚至取消了对它的支持。
有关为什么不再推荐HPKP的其他详细信息,请阅读 Is HTTP Public Key Pinning Dead? and I’m giving up on HPKP
X-Frame-Options
在网站中允许添加frame是一种危险的方式,比如使用一些CSS样式,使frame表现的跟网站一样,导致用户点击了不想要点击的内容,这就是点击攻击

ℹ️ 防止点击攻击的另一种方式是Content Security Policy (CSP)

解决点击劫持问题的一种更现代的方法是使用X-Frame-Options头。默认情况下,Spring Security禁用在iframe内使用以下头呈现页面:

X-Frame-Options: DENY

X-XSS-Protection
一些浏览器内置了对过滤反射的XSS攻击的支持。这绝非万无一失,但确实有助于XSS保护。
过滤通常在默认情况下处于启用状态,因此添加标头通常只会确保其处于启用状态并指示浏览器在检测到XSS攻击时应采取的措施。
Spring Security默认添加一下头:

X-XSS-Protection: 1; mode=block

Content Security Policy (CSP)

Content Security Policy (CSP)是web应用程序可以利用的一种机制,用于缓解内容注入漏洞,如跨站点脚本(XSS)。
web应用程序可以通过在响应中包含以下HTTP头之一来使用CSP:

  • Content-Security-Policy
  • Content-Security-Policy-Report-Only

例如,通过在响应中包含以下标头,web应用程序可以声明希望从特定的可信源加载脚本:
Example 5. Content Security Policy Example

Content-Security-Policy: script-src https://trustedscripts.example.com

如果web应用程序违反了声明的安全策略,以下响应头将指示用户代理向策略的report-uri指令中指定的URL发送违反报告。
Example 6. Content Security Policy with report-uri

Content-Security-Policy: script-src https://trustedscripts.example.com; report-uri /csp-report-endpoint/

违规报告是标准的JSON结构,可以由web应用程序自己的API或公共托管的CSP违规报告服务(如report-uri.com/)捕获。
Content-Security-Policy-Report-Only提供在开发环境的安全策略,用于测试策略是否有效,有效后使用Content-Security-Policy替换。
Example 7. Content Security Policy Report Only

Content-Security-Policy-Report-Only: script-src 'self' https://trustedscripts.example.com; report-uri /csp-report-endpoint/

安全策略相关资料:
An Introduction to Content Security Policy
CSP Guide - Mozilla Developer Network
W3C Candidate Recommendation

Referrer Policy
Referrer Policy是web应用程序可以用来管理Referrer字段的机制。
Spring Security的方法是使用Referrer Policy头,它提供不同的策略:
Example 8. Referrer Policy Example

Referrer-Policy: same-origin

Referrer Policy响应头指示浏览器让目标知道用户以前所在的源。

Feature Policy
允许web开发人员有选择地启用、禁用和修改浏览器中某些API和web功能的行为。
Example 9. Feature Policy Example

Feature-Policy: geolocation 'self'

Permissions Policy
Permissions Policy允许web开发人员有选择地启用、禁用和修改浏览器中某些API和web功能的行为。
Example 10. Permissions Policy Example

Permissions-Policy: geolocation=(self)

Clear Site Data
通过该机制,当HTTP响应包含以下标头时,可以删除任何浏览器端数据(cookie、本地存储等)。

Clear-Site-Data: "cache", "cookies", "storage", "executionContexts"

这是注销时执行的一个很好的清理操作。

Cross-Origin Policies
Spring Security 支持如下跨源头:

Cross-Origin-Opener-Policy(COOP)允许顶级文档打破其窗口与浏览上下文组中任何其他窗口之间的关联(例如,弹出窗口与其打开程序之间的关联),从而阻止它们之间的任何直接DOM访问。
启用Cross-Origin-Embedder-Policy(COEP)可防止文档加载任何不明确授予要加载的文档权限的非同源资源。
Cross-Origin-Resource-Policy(CORP)标头允许您控制授权包含资源的来源集。它是对Spectre等攻击的强大防御,因为它允许浏览器在进入攻击者进程之前阻止给定的响应。

Custom Headers
SpringSecurity有一些机制,可以方便地将更常见的安全标头添加到应用程序中。它还提供了钩子来支持添加自定义头。

HTTP Requests

当客户端使用HTTP时,可以将SpringSecurity配置为重定向到HTTPS Servlet和WebFlux环境。
Spring Security支持Strict Transport Security,并默认启用它。
Spring Boot用户可以使用server.use-forward-headers属性配置应用程序。有关更多详细信息,请参阅Spring Boot文档。

猜你喜欢

转载自blog.csdn.net/weixin_40972073/article/details/127501850