博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
web安全机制问题详解之二:CSRF
阅读量:6292 次
发布时间:2019-06-22

本文共 3299 字,大约阅读时间需要 10 分钟。

什么是CSRF

CSRF(Cross-site request forgery)跨站请求伪造:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击网站执行某项操作的目的。

一个典型的CSRF攻击流程:

  • 用户登录a.com,并保留了登录凭证(cookie)
  • 攻击者引诱用户访问b.com,如,诱导性文字按钮等
  • b.com向a.com发送了一个请求:a.com/act=xx。浏览器会默认携带a.com的cookie
  • a.com接收到请求后,对请求进行验证,并确认是受害用户的凭证,误以为是用户自己发送的请求
  • a.com以用户名义执行了act=xx
  • 攻击完成,攻击者在用户不知情的情况下,冒充用户,让a.com执行了自己定义的操作

例如:

用户A浏览Gmail邮件,因好奇点击了一封“甩卖比特币,只要998”的广告邮件。打开后一片空白,随后用户A关闭了页面。但此时CSRF攻击已经完成,用户A的Gmail邮件将逐一转发到黑客的邮箱。具体是怎么发生的呢,关键在于那个空白页面的源码:

.....
复制代码

这个页面只要一打开就会向Gmail发送一个post请求。请求中,执行了‘Create Filter’命令(自动转发邮件),将所有邮件转发到黑客邮箱hacker@hakermail.com。由于A刚登陆了Gmail,用户登录凭证被保存在cookie中,所以这个空白页发出的post请求就携带了登陆证明,于是成功给用户A配置了过滤器。黑客可以查看所有用户A的邮件,包括一些敏感信息:邮箱验证码等等。此事件原型是2007年Gmail的CSRF漏洞:。目前此漏洞已修复。

几种常见的CSRF攻击

GET类型攻击:http请求时,敏感参数跟在url后面,攻击者很容易获取并发送包含受害者信息的跨域请求。

POST类型攻击:如上案列所示。

链接类型攻击:页面中注入恶意链接,诱导用户点击跳转。

防护策略

据上所示,CSRF通常是由第三方网站发起,因此可以通过增强自身网站的安全性来防御:

  • 同源策略
  • token验证

同源检测

同源策略上分为两部分:一是http请求接口的同源,还有一个是cookie的domain属性的同源。

1. http请求,可以使用origin header、referer header确定来源域名。

在部分请求中,请求的header中会携带origin字段,代表请求的域名;也有不存在origin的情况,IE11对同源的定义有别于其他浏览器,还有一个就是302重定向之后origin不包含在重定向的请求中,因为重定向请求是定向到新的服务器,避免泄露origin信息。

http请求header中还有另外一个记录该请求来源地址的属性referer。referer值是由浏览器提供的,不可排除浏览器自身安全性问题,和部分情况下攻击者隐藏甚至篡改自己请求的referer。在同源策略下,可以把referer属性设置成same-origin,对于同源的额链接和引用会发送referer,对于跨域则不携带referer。

设置referer的三种方法:在csp设置;页面头部增设meta标签;a标签增加referer属性

跳到百度复制代码

但是,在以下情况下referer没有或者不可信:

  • IE6、7使用window.location.href=url进行界面跳转,会丢失referer
  • IE6、7使用window.open,也会丢失referer
  • https跳到http,所有浏览器都会丢失referer
  • 点击flash到达另外一个网站时,referer不可信

2. 在浏览器种下cookie时,若明确cookie的domain属性(一级域名或是子域名),即仅在domain指定的域下的接口才会自动携带cookie,可以解决部分跨域问题,但仍不能避免攻击者伪造的域名和网站同域(本地服务器proxy代理请求时)。还可以设置cookie为Httponly,这样cookie只能在请求中被携带,无法用document.cooke读取、修改。

token验证

这里的token验证也有两种,一种是CSRF token的加解密校验,还有一个是双重Cookie验证。

1. CSRF token

用户打开页面时,服务器会个每个用户生成唯一的token,这个token是经过精密算法对数据进行加密,一般包括随机字符串和时间戳。token会存在服务器的session中。页面提交的请求都会携带这个token,当服务器拿到token后用相应解密算法得到时间戳、及加密字符串,再和服务器session中存储的token信息作比较来判断该请求的有效性,这类token一般是随机字符串。

分布式校验

在大型网站中,使用session存储token会带来很大压力。访问单台服务器session是同一个。但是现在的大型网站中,我们的服务器通常不止一台,可能是几十台甚至几百台之多,甚至多个机房都可能在不同的省份,用户发起的HTTP请求通常要经过像Ngnix之类的负载均衡器之后,再路由到具体的服务器上,由于Session默认存储在单机服务器内存中,因此在分布式环境下同一个用户发送的多次HTTP请求可能会先后落到不同的服务器上,导致后面发起的HTTP请求无法拿到之前的HTTP请求存储在服务器中的Session数据,从而使得Session机制在分布式环境下失效,因此在分布式集群中CSRF Token需要存储在Redis之类的公共存储空间。

目前的解决办法就是采用Encrypted Token Pattern方式,计算出一个结果,而不是随机字符串。这样就无需将token存储在session中,只需要在拿到token的时候再计算一次就行。

Token是一个比较有效的CSRF防护方法,只要页面没有XSS漏洞泄露Token,那么接口的CSRF攻击就无法成功。其次,验证码和密码其实也有CSRF token的作用。

2. 双重Cookie验证

双重Cookie采用以下流程:

  • 在用户访问网站页面时,向请求域名注入一个Cookie,内容为随机字符串(例如csrfcookie=v8g9e4ksfhw)。
  • 在前端向后端发起请求时,取出Cookie,并添加到URL的参数中(接上例POST https://www.a.com/comment?csrfcookie=v8g9e4ksfhw)。
  • 后端接口验证Cookie中的字段与URL参数中的字段是否一致,不一致则拒绝。

此方法相对于CSRF Token就简单了许多。可以直接通过前后端拦截的的方法自动化实现。后端校验也更加方便,只需进行请求中字段的对比,而不需要再进行查询和存储Token。

当然,此方法并没有大规模应用,其在大型网站上的安全性还是没有CSRF Token高,原因我们举例进行说明。

由于任何跨域都会导致前端无法获取Cookie中的字段(包括子域名之间),于是发生了如下情况:

  • 如果用户访问的网站为www.a.com,而后端的api域名为api.a.com。那么在www.a.com下,前端拿不到api.a.com的Cookie,也就无法完成双重Cookie认证。
  • 于是这个认证Cookie必须被种在a.com下,这样每个子域都可以访问。
  • 任何一个子域都可以修改a.com下的Cookie。
  • 某个子域名存在漏洞被XSS攻击(例如upload.a.com)。虽然这个子域下并没有什么值得窃取的信息。但攻击者修改了a.com下的Cookie。
  • 攻击者可以直接使用自己配置的Cookie,对XSS中招的用户再向www.a.com下,发起CSRF攻击。

参考:

转载于:https://juejin.im/post/5c9206e4f265da61003d2eb6

你可能感兴趣的文章
资源文件夹res/raw和assets的使用
查看>>
UINode扩展
查看>>
LINUX常用命令
查看>>
百度云盘demo
查看>>
概率论与数理统计习题
查看>>
初学structs2,简单配置
查看>>
Laravel5.0学习--01 入门
查看>>
时间戳解读
查看>>
sbin/hadoop-daemon.sh: line 165: /tmp/hadoop-hxsyl-journalnode.pid: Permission denied
查看>>
@RequestMapping 用法详解之地址映射
查看>>
254页PPT!这是一份写给NLP研究者的编程指南
查看>>
《Data Warehouse in Action》
查看>>
String 源码浅析(一)
查看>>
Spring Boot 最佳实践(三)模板引擎FreeMarker集成
查看>>
Fescar 发布 0.2.3 版本,支持 Redis 和 Apollo
查看>>
Google MapReduce到底解决什么问题?
查看>>
CCNP-6 OSPF试验2(BSCI)
查看>>
Excel 2013 全新的图表体验
查看>>
openstack 制作大于2TB根分区自动扩容的CENTOS镜像
查看>>
Unbuntu安装遭遇 vmware上的Easy install模式
查看>>