一个银行转账示例带你了解CSRF原理,跨站请求伪造(CSRF)示例原理及其防御措施
Posted Java大厂面试官
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个银行转账示例带你了解CSRF原理,跨站请求伪造(CSRF)示例原理及其防御措施相关的知识,希望对你有一定的参考价值。
概述
例子
模拟银行转账的CSRF攻击。
大致步骤如下:
-
张三登录银行页面 -
张三转账给李四1000元 -
微信接到一个中奖通知连接( 假的) -
点击连接并在其网站点击“ 领奖”按钮 -
发现钱被转走了 100000元。。。
“前提:张三在银行网站一直处于登录状态
这里我搞了个小demo给大家演示下,全部代码在gitee上传送门
1. 张三登录银行页面
2. 张三转账给李四1000元
3. 微信接到一个中奖通知连接(假的)
4. 点击连接并在其网站点击“领奖”按钮
5. 看似点击个“领奖”按钮,实际上操作却是自己银行的钱转给【laker】100000元,裂开了
原理
我们先来看看正常的【张三】转账给【李四】
页面核心源码
<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)示例原理及其防御措施的主要内容,如果未能解决你的问题,请参考以下文章