对于刚刚入门安全的同学来说,csrf是最难理解的概念之一,本文会用最简单的方式对csrf进行讲解,包括csrf的定义,csrf典型的攻击流程以及如何对其进行防范,希望本文能够帮到大家!
CSRF定义
CSRF(Cross Site Request Forgery, 跨站域请求伪造)攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。经典图解如下:
一个典型的CSRF攻击流程
1.受害者登录a.com,并保留了登录凭证(Cookie)。
例如:受害者 Bob 在银行有一笔存款,通过对银行的网站发送请求 http://bank.example/withdraw?account=bob&amount=1000&for=bob2 可以使 Bob 把 1000的存款转到 bob2 的账号下。
2.攻击者引诱受害者访问了b.com,b.com 向 a.com 发送了一个请求:a.com/act=xx
例如:黑客 Kevin 自己在该银行也有账户,他知道上文中的 URL 可以把钱进行转帐操作。Kevin自己做一个网站,在网站中放入如下代码src=”http://bank.example/withdraw?account=bob&amount=1000&for=kevin”,
并且通过广告等诱使 Bob 来访问他的网站。
3.a.com接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是受害者自己发送的请求。a.com以受害者的名义执行了act=xx。
例如:当 Bob 访问该网站时,上述 url 就会从 Bob 的浏览器发向银行,而这个请求会附带 Bob 浏览器中的 cookie 一起发向银行服务器。大多数情况下,该请求会失败,因为他要求 Bob 的认证信息。但是,如果 Bob 当时恰巧刚访问他的银行后不久,他的浏览器与银行网站之间的 session 尚未过期,浏览器的 cookie 之中含有 Bob 的认证信息。这时,这个 url 请求就会得到响应,钱将从 Bob 的账号转移到Kevin 的账号,而 Bob 当时毫不知情。
4.攻击完成,攻击者在受害者不知情的情况下,冒充受害者,让a.com执行了自己定义的操作。
从上面的例子可知,CSRF 攻击是黑客借助受害者的 cookie 骗取服务器的信任,但是黑客并不能拿到 cookie,也看不到 cookie 的内容。黑客无法从返回的结果中得到任何东西,他做的就是给服务器发送请求,执行请求中的用来干坏事的命令,在服务器端改变了数据的值,而非窃取服务器中的数据。所以关于csrf,我们要保护的对象是那些可以直接产生数据改变的服务,而非读取数据的服务。
CSRF防范
防范csrf,通常可以采用如下三种方式:
1.验证 HTTP Referer 字段
请求:http://bank.example/withdraw?account=bob&amount=1000&for=bob2
Referer 的值就会是转账按钮所在的页面的 URL,通常是以 bank.example 域名开头的地址。而如果黑客要对银行网站实施 CSRF 攻击,他只能在他自己的网站构造请求,当用户通过黑客的网站发送请求到银行时,该请求的 Referer 是指向黑客自己的网站。因此,要防御 CSRF 攻击,银行网站只需要对于每一个转账请求验证其 Referer 值,如果是以 bank.example 开头的域名,则说明该请求是来自银行网站自己的请求,是合法的。如果 Referer 是其他网站的话,则有可能是黑客的 CSRF 攻击,拒绝该请求。这种方法是有缺陷的。Referer 的值是由浏览器提供的,虽然 HTTP 协议上有明确的要求,但是每个浏览器对于 Referer 的具体实现可能有差别,并不能保证浏览器自身没有安全漏洞。使用验证 Referer 值的方法,就是把安全性都依赖于第三方(即浏览器)来保障,从理论上来讲,这样并不安全。事实上,对于某些浏览器,比如 IE6,目前已经有一些方法可以篡改 Referer 值。如果 bank.example 网站支持 IE6 浏览器,黑客完全可以把用户浏览器的 Referer 值设为以 bank.example 域名开头的地址,这样就可以通过验证,从而进行 CSRF 攻击。但是随着ie低版本的产品逐步淡出历史舞台,所以大家还是可以放心使用的!
2. 通过csrf token验证
CSRF 攻击之所以能够成功,是因为黑客可以完全伪造用户的请求,该请求中所有的用户验证信息都是存在于 cookie 中,因此黑客可以在不知道这些验证信息的情况下直接利用用户自己的 cookie 来通过安全验证。要抵御 CSRF,关键在于在请求中放入黑客所不能伪造的信息,并且该信息不存在于 cookie 之中。可以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。
具体实现思路如下:
提交需要进行csrf防护的请求到服务器,后台会去查一下session里面,有没有token,如果有的话,就把它销毁掉,然后生成一个新的token,赋值到session里面去。下图实现了
后端生成的token,显示到前端的代码示例:
这个例子对应了一个POST请求,由于token是随机生成的,黑客很难对其进行伪造!如果是
GET 请求,token 将附在请求地址之后,例如 URL http://url?csrftoken=tokenvalue
另外如果在一个应用中多处请求都需要进行csrf进行校验,那么会对应用性能产生一定的影响,需要对此做出平衡。
3.Set-Cookie响应头新增Samesite属性
SameSite属性可以让 Cookie 在跨站请求时不会被发送,从而阻止了跨站请求伪造攻击(CSRF)。它有三个属性值
- Strict 完全禁止第三方 Cookie,跨站点时,任何情况下都不会发送 Cookie。
- Lax 允许部分第三方请求携带 Cookie。
- None 无论是否跨站都会发送 Cookie。
这种方式与HTTP Referer 类似,只不过支持 SameSite需要使用各个浏览器厂商提供的更为高版本的产品,如下图所示:
详情请参考:https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite
CSRF目前已不是高危漏洞
其实,目前csrf已经不算高危安全漏洞了(因为攻击成功概率较小),但是对csrf的理解是非常有助于帮助大家对安全知识的理解和学习的!2021 owasp top10中csrf已经没有上榜了,已经如下图: