web安全(二)——CSRF

产生原理

CSRF 又称XSRF(Cross-site request forgery / one click attack/session riding),中文跨站请求伪造。CSRF与XSS在攻击手段上有点类似,都是在客户端执行恶意代码, 但CSRF不注重于获取用户Cookie。CSRF不仅可以在源站发起攻击,还可以引导用户访问其他危险网站的同时发起攻击。CSRF攻击是源于WEB的隐式身份验证机制,WEB的身份验证机制虽然可以保证一个请求是来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的。
攻击者诱导用户访问一个恶意的网站,就可以利用用户在可信的网站的登陆信息进行恶意操作(删除信息,转账等)。
银行网站A,它以GET请求来完成银行转账的操作,如:http://www.mybank.com/Transfer.php?toBankId=11&money=1000
危险网站B,它里面有一段HTML的代码如下:

<img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000>

银行网站A违反了HTTP规范,使用GET请求更新资源。在访问危险网站B的之前,你已经登录了银行网站A,而B中的以GET的方式请求第三方资源(这里的第三方就是指银行网站了,原本这是一个合法的请求,但这里被不法分子利用了),所以你的浏览器会带上你的银行网站A的 Cookie发出Get请求,去获取资源“http://www.mybank.com/Transfe… money=1000”,结果银行网站服务器收到请求后,认为这是一个更新资源操作(转账操作),所以就立刻进行转账操作。

CORB对CSRF攻击的影响

在新版的Chrome(本人当前版本:67.0.3396.99)中尝试下面代码,会出错。

<img src="http://www.test.com/article/detail?id=58">

因为这个请求返回的是id=59的文章的内容,不是图片格式。浏览器的控制台出现错误信息
这里写图片描述
CORB (Cross-Origin Read Blocking) 是一个屏蔽跨域资源加载的功能。利用img的跨站请求可以发起,只是返回的结果被过滤掉了,在解析图片时出错。这时候跨域的资源其实已经传入到了这个进程里面,结合 spectre 类型的旁路攻击或者其他漏洞是可以拿到这些信息的。 CORB 的想法就是直接屏蔽掉跨域资源返回的结果,让地址空间里都没有返回的结果。目前只有HTML,XML 和 JSON 类型的资源会被 CORB 保护

CSRF攻击成功需要满足如下条件:
  1. 用户在信任的网站A已经登陆
  2. 用户在他在网站A的登陆状态有效的情况下浏览了攻击者的网站B
  3. 网站B向网站A的服务器发起破环用户信息的请求
  4. 网站A的服务器默认网站B中的操作是用户发起的,执行了网站B中发起的请求
XSS与CSRF的区别在于:
  1. XSS攻击需要JavaScript,而CSRF攻击不需要。
  2. XSS攻击要求站点接受恶意代码,而对于CSRF攻击来说,恶意代码位于第三方站点上。过滤用户的输入可以防止恶意代码注入到某个站点,但是它无阻止法恶意代码在第三方站点上运行。
CSRF攻击并没有违反同源策略。

网页不能请求不同源的服务器上的资源,也不能读取不同源的网页的cookie,LocalStorage中的数据。但是以下资源的请求不受同源策略的限制:

<script src="...">script> 
<link rel="stylesheet" href="..."> 
<img src="..."/>
<video><audio>嵌入多媒体资源。
<object>, <embed><applet> 的插件。
@font-face 引入的字体。一些浏览器允许跨域字体( cross-origin fonts),一些需要同源字体(same-origin fonts)。
<frame><iframe> 载入的任何资源(可以使用X-Frame-Options阻止这种形式的跨域交互)

我们平时说的最多的跨域受限的方式是采用ajax的形式请求数据。
而CRSF可以利用上述不受跨域资源影响的标签对目标服务器进行攻击

防御方法

CSRF 攻击对象

在讨论如何抵御 CSRF 之前,先要明确 CSRF 攻击的对象,也就是要保护的对象。CSRF 攻击是攻击者借助受害者的 cookie 骗取服务器的信任,但是攻击者并不能拿到 cookie,也看不到 cookie 的内容。另外,对于服务器返回的结果,由于浏览器同源策略的限制,攻击者也无法进行解析。因此,攻击者无法从返回的结果中得到任何东西,他所能做的就是给服务器发送请求,以执行请求中所描述的命令,在服务器端直接改变数据的值,而非窃取服务器中的数据。所以,我们要保护的对象是那些可以直接产生数据改变的服务,而对于读取数据的服务,则不需要进行 CSRF 的保护。比如银行系统中转账的请求会直接改变账户的金额,会遭到 CSRF 攻击,需要保护。而查询余额是对金额的读取操作,不会改变数据,CSRF 攻击无法解析服务器返回的结果,无需保护。
所以CSRF能成功的一个关键就是攻击者能猜中所有的请求参数,从而伪装成用户发送的。

防御方法主要有以下几种:
1. 验证码——强制用户确定请求是自己发出的。
  这种方法有点是简洁有效,确定是交互体验不佳、验证码可能被破解
2. 验证 Http Referer 字段

referer是http请求头部的一个字段,包含了当前请求页面的来源页面的地址,即表示当前页面是通过此来源页面里的链接进入的。服务端一般使用 Referer 首部识别访问来源,可能会以此进行统计分析、日志记录以及缓存优化等。

Referer: http://www.text.com

一般来说,请求的来源是可以明确的。比如实现银行转账,那么请求是在银行的网站域名(www.bank.com)下的页面上发起的。如果一个转账的请求来自域名为 www.test.com,那么这个请求肯定是一个CSRF攻击。所以我们可以通过referer字段来判断是否发生CSRF。但是有时候我们不一定可以拿到referer,原因是处于隐私保护浏览器不一定发送referer或者某些插件可以自定义referrer。

3.添加 Token 并验证

CSRF关键就是攻击者能猜中所有的请求参数,从而伪装成用户发送的。如果在服务器端随机生成一串随机数,发送给浏览器,要求每次请求都带入这个随机数,服务器再验证发送的随机数是否是之前发送的,来确实请求是否是真实的。这个随机数成为token。攻击者在不知道token的情况下,无法进行CSRF攻击。
token存在哪里呢?对于表单的请求,可以放在每个表单的隐藏的input字段中。每次提交表单信息时,一起发送给服务。或者存放在cookie中。服务器通过设置set-cookie值来设置token的值。客户端代码再在每次发送请求之前,从cookie中读取token的值,手动加到请求参数中。因为同源策略的限制,攻击者的网站B是不能读取目标网站A中的cookie的,所以无法拿到token。所以,token值在传输时,最好用post请求附在http body体中。若采用get请求附在url的参数中,容易被攻击者盗取。同时,token的值最好可以一段时间或者一次请求之后及时更新。此外,token需要足够随机,不然容易被猜测出。

你可能感兴趣的:(Web)