CSRF攻击的解释

下文来源于SpringSecurity官方文档。

CSRF 攻击

在讨论 Spring Security 如何保护应用程序免受 CSRF 攻击之前,我们将解释什么是 CSRF 攻击。让我们看一个具体的例子以获得更好的理解。

假设您的银行网站提供了一种表格,该表格允许将资金从当前登录的用户转移到另一个银行帐户。例如,HTTP 请求可能类似于:

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

amount=100.00&routingNumber=1234&account=9876

现在,Feign 您对银行的网站进行身份验证,然后在不注销的情况下访问一个邪恶的网站。恶意网站包含具有以下格式的 HTML 页面:

<form action="https://bank.example.com/transfer" method="post">
<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>

您想赢钱,因此单击“提交”按钮。在此过程中,您无意中将$ 100 转让给了恶意用户。发生这种情况的原因是,尽管恶意网站无法看到您的 cookie,但与您的银行关联的 cookie 仍与请求一起发送。

同步器令牌模式

问题在于,来自银行网站的 HTTP 请求与来自邪恶网站的请求完全相同。这意味着无法拒绝来自邪恶网站的请求并允许来自银行网站的请求。为了防御 CSRF 攻击,我们需要确保恶意站点无法提供请求中的某些内容。

一种解决方案是使用同步器令牌模式。该解决方案是确保除我们的会话 cookie 之外,每个请求还需要随机生成的令牌作为 HTTP 参数。提交请求后,服务器必须查找参数的期望值,并将其与请求中的实际值进行比较。如果值不匹配,则请求应失败。

我们可以放宽期望,只要求每个更新状态的 HTTP 请求都需要令牌。可以安全地完成此操作,因为相同的来源策略可确保恶意站点无法读取响应。另外,我们不想在 HTTP GET 中包含随机令牌,因为这可能导致令牌泄漏。

让我们看一下示例将如何变化。假设在名为_csrf 的 HTTP 参数中存在随机生成的令牌。例如,转帐的请求如下所示:

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

amount=100.00&routingNumber=1234&account=9876&_csrf=<secure-random>

您会注意到,我们为_csrf 参数添加了一个随机值。现在邪恶网站将无法猜测_csrf 参数的正确值(必须在邪恶网站上明确提供),并且当服务器将实际令牌与预期令牌进行比较时,传输将失败。

何时使用 CSRF 保护

什么时候应该使用 CSRF 保护?我们的建议是对普通用户可能由浏览器处理的任何请求使用 CSRF 保护。如果仅创建非浏览器 Client 端使用的服务,则可能需要禁用 CSRF 保护。

CSRF 保护和 JSON

一个常见的问题是“我需要保护由 javascript 发出的 JSON 请求吗?”简短的答案是,这取决于。但是,您必须非常小心,因为有些 CSRF 漏洞会影响 JSON 请求。例如,恶意用户可以创建使用以下格式的带有 JSON 的 CSRF

<form action="https://bank.example.com/transfer" method="post" enctype="text/plain">
<input name='{"amount":100,"routingNumber":"evilsRoutingNumber","account":"evilsAccountNumber", "ignore_me":"' value='test"}' type='hidden'>
<input type="submit"
	value="Win Money!"/>
</form>

这将产生以下 JSON 结构

{ "amount": 100,
"routingNumber": "evilsRoutingNumber",
"account": "evilsAccountNumber",
"ignore_me": "=test"
}

如果应用程序未验证 Content-Type,则该应用程序将被暴露。根据设置的不同,仍然可以通过更新 URL 后缀以“ .json”结尾来利用可验证 Content Type 的 Spring MVC 应用程序,如下所示:

<form action="https://bank.example.com/transfer.json" method="post" enctype="text/plain">
<input name='{"amount":100,"routingNumber":"evilsRoutingNumber","account":"evilsAccountNumber", "ignore_me":"' value='test"}' type='hidden'>
<input type="submit"
	value="Win Money!"/>
</form>

CSRF 和 Stateless 浏览器应用程序

如果我的应用程序是 Stateless 的怎么办?那并不一定意味着您受到保护。实际上,如果用户不需要针对给定请求在 Web 浏览器中执行任何操作,则他们可能仍然容易受到 CSRF 攻击。

例如,考虑一个应用程序使用一个包含其内所有状态的自定义 cookie 而不是 JSESSIONID 进行身份验证。进行 CSRF 攻击后,自定义 cookie 将与请求一起发送,其方式与在前面的示例中发送 JSESSIONID cookie 相同。

使用基本身份验证的用户也容易受到 CSRF 攻击,因为浏览器将在所有请求中自动包括用户名密码,就像在前面的示例中发送 JSESSIONID cookie 一样。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值