CSRF简述
CSRF全称为Cross Site Request Forgery
,意为跨站请求伪造。是指利用未失效的身份信息(如cookie
等),在受害人不知情的情况下以受害人的身份向服务器发送恶意请求,以此完成恶意操作。
CSRF并非盗取用户身份认证信息,而是直接利用。
攻击形式/原理
假设某社交网站存在CSRF漏洞,其用户Sam在进行修改密码操作时,向服务器的请求URL如下:
http://www.example.com?new_pswd=anything
发送该请求后,服务器将该用户的密码修改为anything
.
由此,攻击者构造恶意URL如下:
http://www.example.com?new_pswd=something
并诱使Sam点击该链接。Sam点击该链接后,浏览器会附带Sam之前访问该社交网站留下的cookie
发出请求,此时若Sam不久前刚登陆过该社交网站(session
未过期),那么这个请求便会完成该修改密码的操作,从而导致Sam在社交网站上的个人信息全部泄露。
作为一次黑客攻击来说,这次CSRF攻击含有重大缺陷,比如:
- 由于该URL为明文,被攻击者可以轻易发现这个链接所代表的意义,由此可能并不会去点击这个链接,导致非法操作失败。
- 用户在点击该链接后,如果修改密码成功,那么会立即看到该社交网站的修改密码成功的通知页面,而因此意识到自己密码已被纂改,并迅速修改密码,导致攻击者并没有时间使用修改后的密码完成恶意操作。
说到这里不得不提一下,常见的钓鱼网站等恶意页面一般都使用短链接隐藏了URL实际内容,导致受害人并不能通过直接观察的方式看出该URL的所属域名、参数等。但即便是这样,其还是无法隐藏操作成功后的服务器端回显内容。
现实中,攻击一般不会直接让被攻击者访问恶意URL,而是使用其他方式间接地、隐秘地使被攻击者在真正不知情的情况下向目标服务器发出请求。
例如在自己的服务器上构建以下页面,诱使受害者访问:
<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
<img src="http://www.example.com?new_pswd=something" border="0" style="display:none;"/>
</body>
</html>
受害者打开之后,看到的是一个404 Not Found
的普通页面,而实际上该页面已经向目标服务器发出了恶意请求。
CSRF漏洞检测
- 一般情况下,一个正常的服务器会有
HTTP
报头检查,使用拦截器检查Referer
头,判断是否来源于本域。(详见后文安全防御机制部分)拦截发送给某服务器的请求,并且尝试去掉其中的Referer
头然后发送表单数据,观察服务器响应是否受到影响。 - 观察请求数据包中的
cookie
值等,观察是否含有不可预测类型的键值,如果无,尝试是否能总结某些非随机数据的取值规则。 - 在本地构建恶意网页,尝试对目标服务器上自己持有的帐号进行CSRF攻击。
常见安全防御机制
1. 验证请求中的Referer
头
该请求头指示了请求来自站内还是站外,如果在服务器端对请求头进行检查,如果来自站外,那么服务器便持怀疑态度,拒绝该请求。这一方法非常便捷,可以拦截一些简单的CSRF攻击,但并不是万无一失。
目前已知很多方法可以篡改该请求头,所以仅仅依靠该方法来判断是绝不可行的。
另外,在一些特殊情况下合法用户可能并不会发出Referer
请求头,如果只借此判断,就有可能拒绝合法用户的合法请求。
由于某些网站可能URL构造复杂,一些没有经验的安全运维人员所设定的程序在进行Referer
的检查时只检查其是否由某个字符串(一般是主站地址)开头,这样攻击者便可以通过修改自己的域名,来进行绕过。
例如若服务器仅检查是否由http://www.example.com...
开头,攻击者构建的攻击页面使用以下域名时便可能被当作本域来源:
http://www.example.comm12345.com/...
2. 加入Token
并验证
在用户访问易受攻击的页面时由服务器返回一个随机的Token
字段,在提交表单时需要一起提交该参数,而服务器在收到请求之后,会优先检查该值是否正确,如果正确,才处理来自客户端的请求。
-
但其有很大局限性:
-
如果该值存放于
Cookie
中,那么便将其他值一样不可信,除非该网站的cookie有效期仅限于完成这一次请求。
如果该值仅限于此一次操作,理论上其实仍然是不安全的:
攻击者完全可以利用被攻击者的浏览器去目标页面获取该Token
并用于自己的恶意操作中。比如在页面中以加入隐秘JS框架去访问目标页面。
但由于同源策略,跨域实际上是不可进行的:
目标服务器与黑客构造的攻击页面所在的域名不同,域名B下的所有页面都不允许主动获取域名A下的页面内容,除非域名A下的页面主动发送信息给域名B的页面。
目前的浏览器均不允许跨域请求。
由于跨域是不可能实现的,只有将代码注入到目标服务器上,才有可能完成CSRF攻击。也就是说,XSS
漏洞很有可能被用于突破反CSRF防御,所以在应对CSRF攻击时,留意对XSS的防御也是极其重要的。
(本文为个人总结整理,如有错误欢迎指正)