CSRF Cross Site Reqiest Forgery 跨站点请求伪造
CSRF 攻击是利用用户的身份操作用户帐户的一种攻击方式
先 搭建一个 SAE 博客,上面可以上传自己写的html 用于后面的csrf 页面
参考: http://jingyan.baidu.com/article/020278118f30e11bcc9ce595.html
在SAE上安装: http://docs.typecho.org/sae-install
eg: 自己博客上上传一个xxx.html 然后构造<img src=http://xxx.com/xxx.do?delete&id=xxxx/> 然后发送这个html 网址给对方,对方一经访问就删除了xxx文章.
我测试了一下,用chrome 实验 CSDN 不行,我抓包查看 发现 能正常删除文章的 请求 是 XMLHttpRequest,为 Ajax 异步请求。但是失败原因不是它,失败原因是referer 不同
COOKIE :
1 Session Cookie 临时cookie
没有指定Expire时间,浏览器关闭后,COOKIE 就失效了
在浏览网站的过程中,若是一个网站设置了Session Cookie,那么在浏览器的生命周期中,即使浏览器新打开了TAB页面,Session Cookie 也都是有效的。
Session Cookie 保存在浏览器进程的内存空间中
2: Third-party Cookie 本地Cookie
是服务器在Ser-Cookie 时指定了 Expire 时间,只有到了 Expire时间后,cookie 才会失效,所以保存在本地
Third-party Cookie 保存在 本地
<script> <img> <iframe> <link> 等标签禁止在 IE 浏览器 发送第三方cookie
FireFox 默认策略是允许 发送第三方cookie
有没有办法不让浏览器刷新 : <iframe>
p3p header Thr Platform for Privacy Preferences
如果网站返回给浏览器的HTTP头中包含P3P头,则在某种程度上,允许浏览器发送第三头 cookie.
在IE下 即使是 <iframe> <script> 等标签都不再拦截 第三方 cookie
主要用于 类似广告的需要跨域访问的页面,设置后,对于COOKIE 影响将扩大到整个域中所有页面,cookie 是以域和path为单位的
flash csrf:
import flash.net.URLRequest;
import flash.system.Security;
var url = new URLRequest("http://xxx/xxx");
var param = new URLVariables();
param = "test=123";
url.method = "POST";
url.data = param;
sendToURL(url);
stop();
版本2:
eq = new LoadVars();
req.addRequestHeader("foo","bar");
req.send("http://xxx/xxx?v1=123&v2=456","_blank","GET");
IE 8开始,FLASH 发起的网络请求 已经不再发送本地cookie了
防御:
1) 验证码
强制用户必须与应用进行交互,才能完成最终请求,因此在通常情况下,验证码可以很好地遏制 CSRF攻击
考虑到用户体验,只能作为辅助手段
2)referer check
最常见的应用 就是 “防止图片盗链”。同理,也可以作为检查请求是否来自合法的 “源”
假如一个 “论坛发帖” 的操作,那么referer 的值必然是 发帖表单所在的页面,如果referer不是这个页面,甚至不是发帖网站的域,那么就极可能是 CSRF攻击了
缺陷:在于 服务器不是什么时候都能取到referer 的,很多时候出于隐私保护的考虑,限制了 rerer的发送, 还有HTTPS 到HTTP的跳转,出于安全考虑,浏览器也不会发送 referer的
所有跨协议传递的请求都是不会送referer的,如https->http,(这个利用成本有点高)还有javascript->http,data->http
在flash的一些版本中,曾经可以 发送自定义的 referer 头,虽然flash 在新版本中已经做了安全限制了,不再允许自动以 referer头,但难免不会有别的客户端的插件允许这种操作
3) 业界的一致做法是使用一个 token
CSRF 本质——重要操作的所有参数能够被攻击者猜到。
把参数加密,或者使用一些随机数,从而让攻击者无法猜到参数值。这事“不可预测性原则”
比如一个删除操作URL: http://xxx/dekete?username=abc&item=123 将username 加密
http://xxx/dekete?username=md5(salt+abc)&item=123
这样在攻击者不知道 salt 的情况下无法构造URL,无法发起CSRF,而服务器可以知道
缺陷: 加密或者混淆后URL将变得非常难读,对用户非常不友好,其次,如果加密的参数每次都改变,则某些URL将无法再被用户收藏
anti csrf token:
http://xxx/delete?username=abc&item=123&token=[random(seed)]
token需要足够随机,实际应用中 token可以在用户的session 中,或者浏览器的 cookie中
每次请求生成一个新的 token,中,那么可以考虑生成多个 有效的 token,以解决多页面共存问题
尽量把 token放在 表单中,防止token泄漏(否则referer中可以查到toen),把敏感操作由GET 换成 POST 以form的形式提交,可以避免token的泄漏
在XSS攻击下,攻击者完全可以请求页面后,读出页面的内容的token值,然后再构造一个合法的请求,这个过程称为 XSRF
在自己的域上构造 html
<html>
<iframe src="data:text/html;base64,base64(<script src=http://xxx/delete?articleId=xxx></script>)" ></iframe>
</html>
提示: <script>alert('非法操作,无法删除!');location.href='http://xxx.xxx.net'</script>
看到 CSDN 有 access-token 那么几种防护都设置了的!