CSRF(Cross Site Request Forgery, 跨站请求伪造)
一、CSRF 背景与介绍
CSRF(Cross Site Request Forgery, 跨站域请求伪造)是一种网络的攻击方式,它在 2007 年曾被列为互联网 20 大安全隐患之一。其他安全隐患,比如 SQL 脚本注入,跨站域脚本攻击等在近年来已经逐渐为众人熟知,很多网站也都针对他们进行了防御。然而,对于大多数人来说,CSRF 却依然是一个陌生的概念。即便是大名鼎鼎的 Gmail, 在 2007 年底也存在着 CSRF 漏洞,从而被黑客攻击而使 Gmail 的用户造成巨大的损失。
二、CSRF 攻击实例
CSRF 攻击可以在受害者毫不知情的情况下以受害者名义伪造请求发送给受攻击站点,从而在并未授权的情况下执行在权限保护之下的操作。比如说,受害者 Bob 在银行有一笔存款,通过对银行的网站发送请求 http://bank.example/withdraw?account=bob&amount=1000000&for=bob2 可以使 Bob 把 1000000 的存款转到 bob2 的账号下。通常情况下,该请求发送到网站后,服务器会先验证该请求是否来自一个合法的 session,并且该 session 的用户 Bob 已经成功登陆。黑客 Mallory 自己在该银行也有账户,他知道上文中的 URL 可以把钱进行转帐操作。Mallory 可以自己发送一个请求给银行:http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory。但是这个请求来自 Mallory 而非 Bob,他不能通过安全认证,因此该请求不会起作用。这时,Mallory 想到使用 CSRF 的攻击方式,他先自己做一个网站,在网站中放入如下代码: src=”http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory ”,并且通过广告等诱使 Bob 来访问他的网站。当 Bob 访问该网站时,上述 url 就会从 Bob 的浏览器发向银行,而这个请求会附带 Bob 浏览器中的 cookie 一起发向银行服务器。大多数情况下,该请求会失败,因为他要求 Bob 的认证信息。但是,如果 Bob 当时恰巧刚访问他的银行后不久,他的浏览器与银行网站之间的 session 尚未过期,浏览器的 cookie 之中含有 Bob 的认证信息。这时,悲剧发生了,这个 url 请求就会得到响应,钱将从 Bob 的账号转移到 Mallory 的账号,而 Bob 当时毫不知情。等以后 Bob 发现账户钱少了,即使他去银行查询日志,他也只能发现确实有一个来自于他本人的合法请求转移了资金,没有任何被攻击的痕迹。而 Mallory 则可以拿到钱后逍遥法外。
三、CSRF 攻击的对象
在讨论如何抵御 CSRF 之前,先要明确 CSRF 攻击的对象,也就是要保护的对象。从以上的例子可知,CSRF 攻击是黑客借助受害者的 cookie 骗取服务器的信任,但是黑客并不能拿到 cookie,也看不到 cookie 的内容。另外,对于服务器返回的结果,由于浏览器同源策略的限制,黑客也无法进行解析。因此,黑客无法从返回的结果中得到任何东西,他所能做的就是给服务器发送请求,以执行请求中所描述的命令,在服务器端直接改变数据的值,而非窃取服务器中的数据。所以,我们要保护的对象是那些可以直接产生数据改变的服务,而对于读取数据的服务,则不需要进行 CSRF 的保护。比如银行系统中转账的请求会直接改变账户的金额,会遭到 CSRF 攻击,需要保护。而查询余额是对金额的读取操作,不会改变数据,CSRF 攻击无法解析服务器返回的结果,无需保护。
四、防护CSRF 攻击
1、Django 提供的 CSRF 防护机制
1、使用原理
django 第一次响应来自某个客户端的请求时,会在服务器端随机生成一个 token,把这个 token 放在 cookie 里。然后每次 POST 请求都会带上这个 token,这样就能避免被 CSRF 攻击
2、原理过程
1、GET 请求不要用有副作用。也就是说任何处理 GET 请求的代码对资源的访问都一定要是“只读“的,所以get方式发送数据不需要设置csrf。
2、在返回的 HTTP 响应的 cookie 里,django 会为你添加一个 csrftoken 字段,其值为一个自动生成的 token
3、在所有的 POST 表单时,必须包含一个 csrfmiddlewaretoken 字段
4、在处理 POST 请求之前,django 会验证这个请求的 cookie 里的 csrftoken 字段的值和提交的表单里的 csrfmiddlewaretoken 字段的值是否一样。如果一样,则表明这是一个合法的请求,否则,这个请求可能是来自于别人的 csrf 攻击,返回 403 Forbidden.
2、Django 里如何使用 CSRF 防护(置防跨站请求伪造功能)
1、全局设置
启用 django.middleware.csrf.CsrfViewMiddleware 这个中间件
2、局部设置
from django.views.decorators.csrf import csrf_exempt,csrf_protect
@csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
@csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。
3、客户端如何正确发送数据才不会被csrf拦截
1、通过form提交
1、模板渲染
在html页面的form表单中添加{%csrf_token%}模板语言,,前提是在后端一定要使用render()的方法返回html数据,因为使用 render()会处理 csrf_token 这个模板语言, 从而自动为表单添加一个名 为 csrfmiddlewaretoken 的 input。
<form method="POST" action="/post-url/">
{% csrf_token %} <div>......</div>
</form>
2、模板渲染原理
默认情况下form表单必须添加红色箭头所指的name和value值才能通过csrf验证,但是只有我们通过render()方法添加上模板语言就可以自动添加
2、通过ajax提交
1、因为cookie中同样存在csrftoken,所以可以在js中通过:$.cooke("cstftoken")获取
在views中的login函数中:from django.conf import settings,然后打印print(settings.CSRF_HEADER_NAME)
print(settings.CSRF_HEADER_NAME)打印的内容为:HTTP_X_CSRFTOKEN
这里的HTTP_X_CSRFTOKEN是django在X_CSRF的前面添加了HTTP_,所以实际传递的是就是X_CSRFtoken,而在前端页面的ajax传递的时候由于不能使用下划线所以传递的是X_CSRFtoken
$("#btn1").click(function () {
$.ajax({
url:"/login/",
type:"POST",
data:{"usr":"root","pwd":"123"},
headers:{ "X-CSRFtoken":$.cookie("csrftoken")},
success:function (arg) { }
})
})
2、如果页面中有多个ajax请求的话就需要在每个ajax中添加headers信息,所以可以通过下面方式在发送ajax请求之前就会自动执行$.ajaxSetup函数,该函数的作用范围是全局ajax;
也可以把beforeSend:function (xhr,settings) { xhr.setRequestHeader("X-CSRFtoken",$.cookie("csrftoken")) }这句话放在ajax的请求头中,该函数的作用范围是局部ajax.
$.ajaxSetup({
beforeSend:function (xhr,settings) {
xhr.setRequestHeader("X-CSRFtoken",$.cookie("csrftoken"))
}
});
3、当发送数据方式为get方式的时候不需要提交csrftoken,为post方式的时候需要,所以该代码可改写成一下方式
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken",$.cookie("csrftoken"));
}
}
});
注释: 这样就实现了当GET|HEAD|OPTIONS|TRACE这些方式请求的时候不需要提交csrftoken
4、通过jQuery插件(通过js代码导入jquery.cookie.js插件,该插件代码如下)
/*!
* jQuery Cookie Plugin v1.4.1
* https://github.com/carhartl/jquery-cookie
*
* Copyright 2013 Klaus Hartl
* Released under the MIT license
*/
(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// CommonJS
factory(require('jquery'));
} else {
// Browser globals
factory(jQuery);
}
}(function ($) { var pluses = /\+/g; function encode(s) {
return config.raw ? s : encodeURIComponent(s);
} function decode(s) {
return config.raw ? s : decodeURIComponent(s);
} function stringifyCookieValue(value) {
return encode(config.json ? JSON.stringify(value) : String(value));
} function parseCookieValue(s) {
if (s.indexOf('"') === 0) {
// This is a quoted cookie as according to RFC2068, unescape...
s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
} try {
// Replace server-side written pluses with spaces.
// If we can't decode the cookie, ignore it, it's unusable.
// If we can't parse the cookie, ignore it, it's unusable.
s = decodeURIComponent(s.replace(pluses, ' '));
return config.json ? JSON.parse(s) : s;
} catch(e) {}
} function read(s, converter) {
var value = config.raw ? s : parseCookieValue(s);
return $.isFunction(converter) ? converter(value) : value;
} var config = $.cookie = function (key, value, options) { // Write if (value !== undefined && !$.isFunction(value)) {
options = $.extend({}, config.defaults, options); if (typeof options.expires === 'number') {
var days = options.expires, t = options.expires = new Date();
t.setTime(+t + days * 864e+5);
} return (document.cookie = [
encode(key), '=', stringifyCookieValue(value),
options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
options.path ? '; path=' + options.path : '',
options.domain ? '; domain=' + options.domain : '',
options.secure ? '; secure' : ''
].join(''));
} // Read var result = key ? undefined : {}; // To prevent the for loop in the first place assign an empty array
// in case there are no cookies at all. Also prevents odd result when
// calling $.cookie().
var cookies = document.cookie ? document.cookie.split('; ') : []; for (var i = 0, l = cookies.length; i < l; i++) {
var parts = cookies[i].split('=');
var name = decode(parts.shift());
var cookie = parts.join('='); if (key && key === name) {
// If second argument (value) is a function it's a converter...
result = read(cookie, value);
break;
} // Prevent storing a cookie that we couldn't decode.
if (!key && (cookie = read(cookie)) !== undefined) {
result[name] = cookie;
}
} return result;
}; config.defaults = {}; $.removeCookie = function (key, options) {
if ($.cookie(key) === undefined) {
return false;
} // Must not alter options, thus extending a fresh object...
$.cookie(key, '', $.extend({}, options, { expires: -1 }));
return !$.cookie(key);
}; }));
注释:html前端通过<script src="/static/plugins/bootstrap/js/bootstrap.js"></script>方式引入该插件
总结:
1、csrf在前端的key为:X-CSRFtoken,到后端的时候django会自动添加HTTP_,并且最后为HTTP_X_CSRFtoken
CSRF(Cross Site Request Forgery, 跨站请求伪造)的更多相关文章
- 转: CSRF(Cross Site Request Forgery 跨站域请求伪造) 背景与介绍
from: https://www.ibm.com/developerworks/cn/web/1102_niugang_csrf/ 在 IBM Bluemix 云平台上开发并部署您的下一个应用 ...
- CSRF(Cross-site request forgery)跨站请求伪造
CSRF 背景与介绍 CSRF(Cross Site Request Forgery, 跨站域请求伪造)是一种网络的攻击方式,它在 2007 年曾被列为互联网 20 大安全隐患之一.其他安全隐患,比如 ...
- CSRF(Cross Site Request Forgery, 跨站域请求伪造)
CSRF(Cross Site Request Forgery, 跨站域请求伪造) CSRF 背景与介绍 CSRF(Cross Site Request Forgery, 跨站域请求伪造)是一种网络的 ...
- Cross-site request forgery 跨站请求伪造
Cross-site request forgery 跨站请求伪造 简称为CSRF或者XSRF,通过伪装来自受信任用户的请求来利用受信任的网站 攻击者盗用了你的身份,以你的名义发送恶意请求,对服务器来 ...
- 浅谈CSRF(Cross-site request forgery)跨站请求伪造
本文目录 CSRF是什么 CSRF攻击原理 CSRF攻击防范 CSRF是什么 CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack” ...
- CSRF Cross-site request forgery 跨站请求伪造
跨站请求伪造目标站---无知用户---恶意站 http://fallensnow-jack.blogspot.com/2011/08/webgoat-csrf.html https://wiki.ca ...
- Django:CSRF(Cross-request forgery)跨站请求伪造
一.CSRF是什么 二.CSRF攻击原理 三.CSRF攻击防范 一.CSRF是什么 CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Atta ...
- CSRF(跨站请求伪造)攻击
CSRF(跨站请求伪造)攻击 CSRF(Cross Site Request Forgery,跨站请求伪造)是一种近年来才逐渐被大众了解的网络攻击方式,又被称为One-Click Attack或Ses ...
- web前端安全 XSS跨站脚本 CSRF跨站请求伪造 SQL注入
web安全,从前端做起,总结下web前端安全的几种技术: 1,XSS XSS的全称是Cross Site Scripting,意思是跨站脚本,XSS的原理也就是往HTML中注入脚本,HTML指定了脚本 ...
随机推荐
- 从第三方Launcher授权启动指定APP的设计与实现
Case 背景: Case要求从第三方Launcher中首次启动指定的应用程序时.弹出对话框提示用户进行授权启动,若用户未授权,则在下次再次启动该应用时依旧弹出对话框提示用户进行授权.直到用户相应用进 ...
- Python内置函数之callable()
callable()用来检测对象是否可调用的. callable()返回值为True或者False. 下面看看例子 : >>> callable() False >>&g ...
- git设置及常用命令
下载 下载地址:https://git-scm.com/downloads windows系统安装 默认安装即可. 其它系统安装方式请自行百度,网上教程很多. 设置 windows桌面右键,选择Git ...
- bonjour的使用
os中,bonjour是一个零配置的网络服务分发服务器与客户端. 在使用bonour之前你应该明白的是,bonjour并不负责数据传输,只负责发布服务与检索服务,并在客户端获取服务端的信息. ...
- python 开发技巧(2)-- Django的安装与使用
一.安装Django pip3 install django 或者直接使用PyCharm安装 参考 二.添加环境变量 将 "(python安装路径)\Scripts" 添加到环境变 ...
- Web应用程序使用Hibernate
在本文中,我们将学习使用hibernate创建一个Web应用程序. 对于创建Web应用程序,我们使用JSP表示逻辑层,使用Bean类表示数据,以及使用DAO类操作数据库.在hibernate中创建简单 ...
- js array filter pop push shift unshift方法
JavaScript Array filter() 方法 JavaScript Array 对象 实例 返回数组 ages 中所有元素都大于 18 的元素: var ages = [32, 33, ...
- chm文件无法阅读
当我们费劲千辛万苦从网上下载好chm文件资料后,打开后发现竟然是这个样子的: 其中主要原因是CHM文件被阻止显示了,CHM文件在NTFS格式的硬盘里的时候就会被阻止显示.我们返回我的电脑,点中我们存放 ...
- sql server 2008获取表的字段注释
SELECT 表名 then d.name else '' end, 表说明 then isnull(f.value,'') else '' end, 字段序号=a.colorder, 字段名=a.n ...
- 【BZOJ1811】[Ioi2005]mea 乱搞
[BZOJ1811][Ioi2005]mea Description 考虑一个非递减的整数序列 S1,....Sn+1(Si<=Si+1 1<=i<=n). 序列M1...Mn是定义 ...