CSRF
跨站域请求伪造, 通过伪装来自受信任用户的庆七一来利用受信任的网站
攻击者盗用了你的身份,伪装成你发送恶意请求。它做的事情是:以你的名义发邮件,发消息,盗取你的账号,甚至购买商品,造成个人隐私泄密和财产安全
原理
1.登录受信任网站A,会生成一个本地的cookie
2.在不登出A的情况下,访问危险网站B
类型
get型的csrf
img中嵌入url的get请求,如果黑客将网址替换crsf的地址就完成攻击了
<img src=http://wooyun.org/csrf?xx=11 />
post类型的csrf
自动提交表单
<form action=http://wooyun.org/csrf.php method=POST>
<input type="text" name="xx" value="11" />
</form>
<script> document.forms[0].submit(); </script>
防御
1. 验证HTTP Referer字段(referer表明来源网站)
优点: 简单易行,普通开发人员不需要担心csrf漏洞,只需要给所有的安全敏感请求增加一个拦截器来检查referer的值是不是自己网站的请求
缺点: 这个方法是为完全依赖浏览器的,并不安全,而且有些浏览器可以篡改referer值,并且referer会记录用户的访问来源,有些隐私客户并不想泄露出去,就去设置浏览器在发送请求的时候不提供referer值,这个时候验证referer值并没有用
2. 在请求地址中添加token并验证
优点: 比referer更加安全,在http请求中以参数的形式加入一个随机产生的token,并在服务器建立一个拦截器来验证这个token,token在用户登录后产生并放入session中,然后每次请求拿出token
**缺点:**对于一些框架来说很麻烦,要手动添加,难以保证token本身的安全,黑客本身在论坛发表内容,可以发布自己的网站,这个黑客就可以得到token,发动攻击。这个时候可以验证来源
3. 在HTTP头中自定义属性并验证
放在http头中自定义属性中
防御实例
1.验证referer
// 从 HTTP 头中取得 Referer 值
var referer=req.headers.Referer;
// 判断 Referer 是否以 test.example 开头
if((referer!=null) && (_.startsWith(referer, “test.example ”)){
// 验证通过
}else{
// 验证失败,返回错误
}
2.验证请求的token
var session = req.session;
// 从 session 中得到 csrftoken 属性
var token = session.csrftoken;
if(token == null){
// 产生新的 token 放入 session 中
token = generateToken();
token.csrftoken = token ;
return ....
} else{
// 从 HTTP 头中取得 csrftoken
var token = req.headers.csrftoken;
// 从请求参数中取得 csrftoken
var xhrToken = req.param('csrftoken');
if(token != null && xhrToken != null && token.equals(xhrToken)){
return ...
}else{
return ... // ERROR
}
}
- 自定义token
var plainXhr = dojo.xhr;
// 重写 dojo.xhr 方法
dojo.xhr = function(method,args,hasBody) {
// 确保 header 对象存在
args.headers = args.header || {};
tokenValue = '<%=request.getSession(false).getAttribute("csrftoken")%>';
var token = dojo.getObject("tokenValue");
// 把 csrftoken 属性放到头中
args.headers["csrftoken"] = (token) ? token : " ";
return plainXhr(method,args,hasBody);
};