跨站请求伪造(CSRF)攻击

一、什么是CSRF攻击?

了解CSRF(Cross-site request forgery,跨站请求伪造)攻击的最好方法是看一个具体的例子。

假设你的银行网站提供了一个表单(form),允许将当前登录的用户的钱转到另一个银行账户。例如,这个转账表格可能看起来像下面这样。

Example 1. Transfer form

<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请求可能看起来下面这样。

Example 2. Transfer HTTP request

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页面,上面有以下表单(form)。

Example 3. Evil transfer form

<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="Win Money!"/>
</form>

你喜欢赢钱(Win Money),所以你点击了提交按钮。在这个过程中,你无意中把100美元转给了一个恶意的用户。发生这种情况的原因是,虽然“邪恶网站”看不到你的cookie,但与你的银行相关的cookie仍然与请求一起被发送。

更糟糕的是,这整个过程本来可以通过使用JavaScript自动完成。这意味着你甚至不需要点击这个按钮。此外,在访问一个遭受 XSS攻击 的“诚实网站”时,它也可能很容易发生。那么,我们如何保护我们的用户免受此类攻击?

二、如何防范CSRF攻击?

CSRF攻击之所以可能,是因为来自受害者网站的HTTP请求和来自攻击者网站的请求是完全相同的。这意味着没有办法拒绝来自“邪恶网站”的请求而只允许来自银行网站的请求。为了防止CSRF攻击,我们需要确保请求中存在“邪恶网站”无法提供的东西,这样我们就可以区分这两个请求。

Spring提供了两种机制来防止CSRF攻击:

  • 同步令牌(Synchronizer Token)模式
  • 在你的 session cookie 上指定 SameSite 属性

1、同步令牌(Synchronizer Token)模式

防止CSRF攻击的最主要和最全面的方法是使用 Synchronizer Token 模式。这个解决方案是确保每个HTTP请求除了需要我们的会话cookie外,还需要在HTTP请求中出现一个被称为CSRF令牌的安全随机生成值。

当一个HTTP请求被提交时,服务器必须查找预期的CSRF令牌,并将其与HTTP请求中的实际CSRF令牌进行比较。如果数值不匹配,HTTP请求应被拒绝。

这个工作的关键是,实际的CSRF令牌应该在HTTP请求的某个部分,而不是由浏览器自动包含。例如,在HTTP参数或HTTP header 中要求实际的CSRF令牌可以防止CSRF攻击。在cookie中要求实际的CSRF令牌不起作用,因为cookie会被浏览器自动包含在HTTP请求中。

我们可以放宽预期,只要求每个更新应用程序状态的HTTP请求提供实际的CSRF令牌。要做到这一点,我们的应用程序必须确保 Safe Method 必须是幂等的。这提高了可用性,因为我们希望允许从外部网站链接到我们的网站。此外,我们不希望在HTTP GET中包含随机令牌(Token),因为这可能导致令牌被泄露。

考虑一下当我们使用 Synchronizer Token 模式时,我们的例子会有什么变化。假设实际的CSRF令牌被要求放在一个名为 _csrf 的HTTP参数中。我们的应用程序的传输形式将看起来像下面一样。

Example 4. Synchronizer Token Form

<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>

表单现在包含一个隐藏的 input,其中有CSRF令牌的值。外部网站无法读取CSRF令牌,因为相同的起源策略确保“邪恶网站”无法读取响应。

相应的转移资金的HTTP请求看起来是这样的。

Example 5. Synchronizer Token request

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

你会注意到,现在的HTTP请求包含了 _csrf 参数的安全随机值。“邪恶网站”将无法为 _csrf 参数提供正确的值(必须在“邪恶网站”上明确提供),当服务器将实际的CSRF令牌与预期的CSRF令牌进行比较时,传输将会失败。

2、SameSite 属性

防止 CSRF攻击 的一个新方法是在cookie上指定 the SameSite 属性。服务器可以在设置cookie时指定 SameSite 属性,以表明来自外部网站的cookie不应该被发送。

一个例子,带有 SameSite 属性的HTTP响应头可能看起来像下面这样。

Example 6. SameSite HTTP response

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

SameSite 属性的有效值如下。

  • Strict: 当指定时,任何来自 同一站点 的请求都包括该cookie。否则,cookie不包括在HTTP请求中。

  • Lax: 当指定时,当来自 同一站点 或请求来自顶级导航且 Safe Method 必须是幂等的 时,将发送cookie。否则,cookie不包括在HTTP请求中。

考虑一下我们的例子如何使用 SameSite 属性进行保护。银行应用程序可以通过在会话cookie上指定 SameSite 属性来防止CSRF。

在我们的 Session cookie 上设置了 SameSite 属性后,浏览器会在来自银行网站的请求中继续发送 JESSIONID cookie。然而,在来自“邪恶网站”的传输请求中,浏览器不再发送 JESSIONID cookie。由于session 不再出现在来自“邪恶网站”的传输请求中,应用程序被保护免受CSRF攻击。

在使用 SameSite 属性保护CSRF攻击时,有一些重要的 注意事项 需要注意。

将 SameSite 属性设置为 Strict 提供了更强的防御,但会使用户感到困惑。考虑到一个用户一直在登录一个托管在 social.example.com 的社交媒体网站。该用户在 email.example.org ,收到一封电子邮件,其中包括一个指向该社交媒体网站的链接。如果用户点击了这个链接,他们理所当然地期望被认证到该社交媒体网站。然而,如果 SameSite 属性是 Strict 的,cookie将不会被发送,因此用户将不会被认证。

另一个明显的考虑是,为了使 SameSite 属性能够保护用户,浏览器必须支持 SameSite 属性。大多数现代浏览器确实 支持 SameSite 属性。然而,仍在使用的旧版浏览器可能不支持。

由于这个原因,我们通常建议将 SameSite 属性作为深度防御,而不是唯一的保护措施来防止CSRF攻击。

3、验证 HTTP Request 中的 Referer 字段

根据 HTTP 协议,在 HTTP 请求头中有一个字段 Referer,它记录了该 HTTP 请求的来源地址。通常情况下,访问一个安全受限页面的请求来自于同一个网站,在后台请求验证其 Referer 值,如果是以自身安全网站开头的域名,则说明该请求是合法的。如果 Referer 是其他网站,则有可能是黑客的 CSRF 攻击,拒绝该请求。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值