CSRF(Cross Site Request Forgeries)跨网站请求伪造,也叫XSRF,通过伪装来自受信任用户的请求来攻击利用受信任网站。
与对比
xss:本网站运行了来自其它网站的脚本
csrf:其它网站对本网站产生了影响
一、攻击
利用用户登录态伪造http请求。
危害:
盗取用户资金(网上银行,购物)
冒充用户发帖(广告帖)
损坏网站名誉
1、 get攻击
最简单的CSRF攻击:
用户Alice登录访问某有csrf漏洞的银行网站http://www.examplebank.com。
Alice被某些信息诱导访问危险网站B。
危险网站B上有一个<img>标签<img class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="http://www.examplebank.com/from=Alice&amount=100&to=Bob">
这个img标签的src不指向图片,而是一个http请求,这个请求让银行服务器从Alice转100到Bob账户上,由于Alice已经登录,浏览器发请求时候会带上cookie骗取服务器信任得到响应。
这样Alice的钱就被悄悄转走了。
<a href="http:xxx.com/xxx">点击</a>
<img class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="http:xxx.com/xxx">
网络蠕虫。
涉及敏感操作的请求改为POST请求。
2、post攻击
危险网站伪造一个隐藏的表单,在onload事件中,触发表单的提交事件。
为防止跳转,可以加一个隐藏的iframe,在iframe中处理提交的请求。
二、防范
伪造http请求特点:
B网站向A网站请求
带A网站Cookies,但是B拿不到cookie,也看不到cookie内容
不访问A网站前端
referer为B网站
1、禁止第三方网站带Cookies
same-site属性:Strict,Lax
header('Set-Cookie: test=12345; SameSite=Lax')
缺点:兼容性
2、验证码
B 不访问A网站前端,所以在A前端页面加入随机验证码来识别请求是不是用户主动发起的。B网站无法伪造一个完整请求。
node中ccap模块可以生成验证码:npm install ccap
优点:简单粗暴,低成本,可靠。
缺点:用户不友好。每次都要填,验证码输入错误要重填。
3、使用内置隐藏变量
服务器生成一串不重复的随机数,用md5编码后【也可以cookie hash生成】,一份存在session中,一份放在隐藏域中随请求提交。B不访问A网站前端所以拿不到token,也没办法拿到cookie中的token。
可以存session,也可以存cookie。。
var csrfToken=parseInt(Math.random()*9999999,10);
ctx.cookies.set('csrfToken',csrfToken);
缺点:没法处理ajax请求。
也可以存在页面的meta中。【处理ajax请求】
<meta name="csrf_token" content="4374023">
缺点:用户打开很多个窗口,只有最后一个页面能成功提交,前面页面会出错,因为cookie中只能存一个tooken。
4、检查网页来源
referer是HTTP请求头,包含请求来源地址。【正确单词是referrer,但是规范中就是错的】
服务器知道正确来源。 验证referer禁止来自第三方网站的请求。
req.headers.referer拿到。
file本地协议访问和http协议访问有点不一样,不会发送referer。
if(referer.indexof('localhost')===-1){
throw new Error('非法请求');
}
检查post提交时候的来源,来源不正确进行清空数据,返回403提示等错误处理。
问题:
B网站后面加上http://127.0.0.1:4200/csrf.html?haha=localhost。就可以匹配成功了。
解决:用正则去匹配。
if(/^https?:\/\/localhost/.test(referer)){
}
缺点:有些浏览器允许用户指定没有referer。需要对referer为空时候进行取舍,要不要通过。
Referer值会记录访问来源,有些用户认为侵犯自己隐私权,有些用户可能会开启浏览器防止跟踪功能,不提供Referer,导致正常用户请求被拒绝。
共同学习,写下你的评论
评论加载中...
作者其他优质文章