一个银行转账示例带你了解CSRF原理,跨站请求伪造(CSRF)示例原理及其防御措施

Posted Java大厂面试官

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个银行转账示例带你了解CSRF原理,跨站请求伪造(CSRF)示例原理及其防御措施相关的知识,希望对你有一定的参考价值。

概述

例子

模拟银行转账的CSRF攻击。

大致步骤如下:

  • 张三登录银行页面
  • 张三转账给李四1000元
  • 微信接到一个中奖通知连接( 假的)
  • 点击连接并在其网站点击“ 领奖”按钮
  • 发现钱被转走了 100000元。。。

前提:张三在银行网站一直处于登录状态

这里我搞了个小demo给大家演示下,全部代码在gitee上传送门

1. 张三登录银行页面

2. 张三转账给李四1000元

一个银行转账示例带你了解CSRF原理,跨站请求伪造(CSRF)示例、原理及其防御措施

3. 微信接到一个中奖通知连接(假的)

一个银行转账示例带你了解CSRF原理,跨站请求伪造(CSRF)示例、原理及其防御措施
在这里插入图片描述

4. 点击连接并在其网站点击“领奖”按钮

一个银行转账示例带你了解CSRF原理,跨站请求伪造(CSRF)示例、原理及其防御措施

5. 看似点击个“领奖”按钮,实际上操作却是自己银行的钱转给【laker】100000元,裂开了

一个银行转账示例带你了解CSRF原理,跨站请求伪造(CSRF)示例、原理及其防御措施

原理

我们先来看看正常的【张三】转账给【李四】

页面核心源码

<input type="text" name="amount"/>
<input type="text" name="acct"/>
$.get("http://localhost:8080/transfer", {acct: acct, amount: amount},

请求详情如下:

Request URL: http://localhost:8080/transfer?acct=%E6%9D%8E%E5%9B%9B&amount=1000
Request Method: GET
Status Code: 200
Remote Address: [::1]:8080
Referrer Policy: strict-origin-when-cross-origin
Connection: keep-alive
Cookie: JSESSIONID=2F0E89DE8B34BBAE3D4D388889681648
Host: localhost:8080
Referer: http://localhost:8080/
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/87.0.4280.66 Safari/537.36

我们再来看看CSRF的【张三】转账给【laker】

页面核心源码

<a href="http://localhost:8080/transfer?acct=laker&amount=100000">恭喜中奖了,点我领奖!</a>

请求详情如下:

Request URL: http://localhost:8080/transfer?acct=laker&amount=100000
Request Method: GET
Status Code: 200
Remote Address: [::1]:8080
Referrer Policy: strict-origin-when-cross-origin
Connection: keep-alive
Cookie: JSESSIONID=2F0E89DE8B34BBAE3D4D388889681648
Host: localhost:8080
Referer: http://localhost:63342/
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36

重点剖析

在这个http://localhost:63342伪造的网站上,当你点击了“领奖”按钮,实际上是发起了http://localhost:8080/transfer?acct=laker&amount=100000请求,并且会自动携带上http://localhost:8080的cookie(如上面的:Cookie: JSESSIONID=2F0E89DE8B34BBAE3D4D388889681648),为什么为自动携带呢?这是浏览器的标准,标准就是这样规定的,常用的单点登录、第三方登录都会用到这个特性。

这就是CSRF攻击的原理,利用cookie的自动携带特性,在其他的网站向你的网站发送请求,如果你的网站中的用户没有退出登录,而发送的请求又是一些敏感的操作请求,比如:转账,那么将会给你的网站的用户带来巨大的损失。

防御

使用token验证

既然CSRF的原理是使用cookie造成的,那不使用cookie就完事了,使用token放在Http hearder中去判断登录状态。

目前架构大部分都是前后端分离的,其使用的就是token验证了。

判断Referer/Origin

可以看到异常的网站其Referer是不同的

SameSite Cookie属性

谷歌提出了same-site cookies概念,same-site cookies 是基于 Chrome 和 Mozilla 开发者花了三年多时间制定的 IETF 标准。它是在原有的Cookie中,新添加了一个SameSite属性,它标识着在非同源的请求中,是否可以带上Cookie,它可以设置为3个值,分别为:

  • Strict
  • Lax
  • None

Cookie中的内容为:

POST /transfer HTTP/1.1
Host: www.a-bank.com
Cookie: JSESSIONID=randomid;SameSite=Strict;

Strict是最严格的,它完全禁止在跨站情况下,发送Cookie。只有在自己的网站内部发送请求,才会带上Cookie。不过这个规则过于严格,会影响用户的体验。比如在一个网站中有一个链接,这个链接连接到了GitHub上,由于SameSite设置为Strict,跳转到GitHub后,GitHub总是未登录状态。

Lax的规则稍稍放宽了些,大部分跨站的请求也不会带上Cookie,但是一些导航的Get请求会带上Cookie,如下:

请求类型 示例 Lax情况
链接 <a href="..."></a> 发送 Cookie
预加载 <link rel="prerender" href="..."/> 发送 Cookie
GET 表单 <form method="GET" action="..."> 发送 Cookie
POST 表单 <form method="POST" action="..."> 不发送
iframe <iframe ></iframe> 不发送
AJAX $.get("...") 不发送
Image <img > 不发送

上面的表格就是SameSite设置为Lax的时候,Cookie的发送情况。

None就是关闭SameSite属性,所有的情况下都发送Cookie。不过SameSite设置None,还要同时设置Cookie的Secure属性,否则是不生效的。

以上就是在前端通过Cookie的SameSite属性防御CSRF攻击,不过大家在使用SameSite属性时,要注意浏览器是否支持SameSite属性。

参考:

  • https://owasp.org/www-community/attacks/csrf
  • https://www.jianshu.com/p/01bec7059ed4

往期推荐




以上是关于一个银行转账示例带你了解CSRF原理,跨站请求伪造(CSRF)示例原理及其防御措施的主要内容,如果未能解决你的问题,请参考以下文章

csrf跨站请求伪造

跨站请求伪造(CSRF攻击)理解

CSRF的攻击与防御

CSRF的攻击与防御

CSRF跨站请求伪造的安全防护

跨站请求伪造CSRF原理