# 第一节:CSRF攻击
# CSRF攻击:
### CSRF攻击概述:
CSRF(Cross Site Request Forgery, 跨站域请求伪造)是一种网络的攻击方式,它在 2007 年曾被列为互联网 20 大安全隐患之一。其他安全隐患,比如 SQL 脚本注入,跨站域脚本攻击等在近年来已经逐渐为众人熟知,很多网站也都针对他们进行了防御。然而,对于大多数人来说,CSRF 却依然是一个陌生的概念。即便是大名鼎鼎的 Gmail, 在 2007 年底也存在着 CSRF 漏洞,从而被黑客攻击而使 Gmail 的用户造成巨大的损失。
### CSRF攻击原理:
网站是通过`cookie`来实现登录功能的。而`cookie`只要存在浏览器中,那么浏览器在访问这个`cookie`的服务器的时候,就会自动的携带`cookie`信息到服务器上去。那么这时候就存在一个漏洞了,如果你访问了一个别有用心或病毒网站,这个网站可以在网页源代码中插入js代码,使用js代码给其他服务器发送请求(比如ICBC的转账请求)。那么因为在发送请求的时候,浏览器会自动的把`cookie`发送给对应的服务器,这时候相应的服务器(比如ICBC网站),就不知道这个请求是伪造的,就被欺骗过去了。从而达到在用户不知情的情况下,给某个服务器发送了一个请求(比如转账)。
### 防御CSRF攻击:
CSRF攻击的要点就是在向服务器发送请求的时候,相应的`cookie`会自动的发送给对应的服务器。造成服务器不知道这个请求是用户发起的还是伪造的。这时候,我们可以在用户每次访问有表单的页面的时候,在网页源代码中加一个随机的字符串叫做`csrf_token`,在`cookie`中也加入一个相同值的`csrf_token`字符串。以后给服务器发送请求的时候,必须在`body`中以及`cookie`中都携带`csrf_token`,服务器只有检测到`cookie`中的`csrf_token`和`body`中的`csrf_token`都相同,才认为这个请求是正常的,否则就是伪造的。那么黑客就没办法伪造请求了。在`Django`中,如果想要防御`CSRF`攻击,应该做两步工作。第一个是在`settings.MIDDLEWARE`中添加`CsrfMiddleware`中间件。第二个是在模版代码中添加一个`input`标签,加载`csrf_token`。示例代码如下:
- 服务器代码:
```
<pre class="calibre12">```
MIDDLEWARE = [
<span class="hljs-string">'django.middleware.security.SecurityMiddleware'</span>,
<span class="hljs-string">'django.middleware.gzip.GZipMiddleware'</span>,
<span class="hljs-string">'django.contrib.sessions.middleware.SessionMiddleware'</span>,
<span class="hljs-string">'django.middleware.common.CommonMiddleware'</span>,
<span class="hljs-string">'django.middleware.csrf.CsrfViewMiddleware'</span>,
<span class="hljs-string">'django.contrib.auth.middleware.AuthenticationMiddleware'</span>,
<span class="hljs-string">'django.contrib.messages.middleware.MessageMiddleware'</span>,
<span class="hljs-string">'django.middleware.clickjacking.XFrameOptionsMiddleware'</span>
]
```
```
- 模版代码:
```
<pre class="calibre12">```
<span class="hljs-tag"><<span class="hljs-class">input</span> <span class="hljs-class">type</span>=<span class="hljs-string">"hidden"</span> <span class="hljs-class">name</span>=<span class="hljs-string">"csrfmiddlewaretoken"</span> <span class="hljs-class">value</span>=<span class="hljs-string">"{{ csrf_token }}"</span>/></span>
```
```
或者是直接使用`csrf_token`标签,来自动生成一个带有`csrf token`的`input`标签:
```
<pre class="calibre12">```
{% csrf_token %}
```
```
## 使用ajax处理csrf防御:
如果用`ajax`来处理`csrf`防御,那么需要手动的在`form`中添加`csrfmiddlewaretoken`,或者是在请求头中添加`X-CSRFToken`。我们可以从返回的`cookie`中提取`csrf token`,再设置进去。示例代码如下:
```
<pre class="calibre12">```
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getCookie</span>(<span class="hljs-params">name</span>) </span>{
<span class="hljs-keyword">var</span> cookieValue = <span class="hljs-params">null</span>;
<span class="hljs-keyword">if</span> (<span class="hljs-params">document</span>.cookie && <span class="hljs-params">document</span>.cookie !== <span class="hljs-string">''</span>) {
<span class="hljs-keyword">var</span> cookies = <span class="hljs-params">document</span>.cookie.split(<span class="hljs-string">';'</span>);
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-params">0</span>; i < cookies.length; i++) {
<span class="hljs-keyword">var</span> cookie = jQuery.trim(cookies[i]);
<span class="hljs-title">// Does this cookie string begin with the name we want?</span>
<span class="hljs-keyword">if</span> (cookie.substring(<span class="hljs-params">0</span>, name.length + <span class="hljs-params">1</span>) === (name + <span class="hljs-string">'='</span>)) {
cookieValue = <span class="hljs-params">decodeURIComponent</span>(cookie.substring(name.length + <span class="hljs-params">1</span>));
<span class="hljs-keyword">break</span>;
}
}
}
<span class="hljs-keyword">return</span> cookieValue;
}
<span class="hljs-keyword">var</span> myajax = {
<span class="hljs-string">'get'</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">args</span>) </span>{
args[<span class="hljs-string">'method'</span>] = <span class="hljs-string">'get'</span>;
<span class="hljs-keyword">this</span>.ajax(args);
},
<span class="hljs-string">'post'</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">args</span>) </span>{
args[<span class="hljs-string">'method'</span>] = <span class="hljs-string">'post'</span>;
<span class="hljs-keyword">this</span>._ajaxSetup();
<span class="hljs-keyword">this</span>.ajax(args);
},
<span class="hljs-string">'ajax'</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">args</span>) </span>{
$.ajax(args);
},
<span class="hljs-string">'_ajaxSetup'</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
$.ajaxSetup({
beforeSend: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">xhr, settings</span>) </span>{
<span class="hljs-keyword">if</span> (!<span class="hljs-tag">/^(GET|HEAD|OPTIONS|TRACE)$/</span>.test(settings.type) && !<span class="hljs-keyword">this</span>.crossDomain) {
xhr.setRequestHeader(<span class="hljs-string">"X-CSRFToken"</span>, getCookie(<span class="hljs-string">'csrftoken'</span>));
}
}
});
}
};
$(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
$(<span class="hljs-string">"#submit"</span>).click(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">event</span>) </span>{
event.preventDefault();
<span class="hljs-keyword">var</span> email = $(<span class="hljs-string">"input[name='email']"</span>).val();
<span class="hljs-keyword">var</span> money = $(<span class="hljs-string">"input[name='money']"</span>).val();
myajax.post({
<span class="hljs-string">'url'</span>: <span class="hljs-string">'/transfer/'</span>,
<span class="hljs-string">'data'</span>:{
<span class="hljs-string">'email'</span>: email,
<span class="hljs-string">'money'</span>: money
},
<span class="hljs-string">'success'</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">data</span>) </span>{
<span class="hljs-params">console</span>.log(data);
},
<span class="hljs-string">'fail'</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">error</span>) </span>{
<span class="hljs-params">console</span>.log(error);
}
});
})
});
```
```
### iframe相关知识:
1. `iframe`可以加载嵌入别的域名下的网页。也就是说可以发送跨域请求。比如我可以在我自己的网页中加载百度的网站,示例代码如下:```
<pre class="calibre12">```
<span class="hljs-tag"><<span class="hljs-class">iframe</span> <span class="hljs-class">src</span>=<span class="hljs-string">"http://www.baidu.com/"</span>></span>
<span class="hljs-tag"></<span class="hljs-class">ifrmae</span>></span>
```
```
2. 因为`iframe`加载的是别的域名下的网页。根据[同源策略](https://baike.baidu.com/item/%E5%90%8C%E6%BA%90%E7%AD%96%E7%95%A5/3927875?fr=aladdin),`js`只能操作属于本域名下的代码,因此`js`不能操作通过`iframe`加载来的`DOM`元素。
3. 如果`ifrmae`的`src`属性为空,那么就没有同源策略的限制,这时候我们就可以操作`iframe`下面的代码了。并且,如果`src`为空,那么我们可以在`iframe`中,给任何域名都可以发送请求。
4. 直接在`iframe`中写`html`代码,浏览器是不会加载的。
- Introduction
- 第一章:学前准备
- 第一节:虚拟环境
- 第二节:准备工作
- 第三节:Django介绍
- 第四节:URL组成部分
- 第二章:URL与视图
- 第一节:第一个Django项目
- 第二节:视图与URL分发器
- 第三章:模板
- 第一节:模板介绍
- 第二节:模板变量
- 第三节:常用标签
- 第四节:常用过滤器
- 第五节:自定义过滤器
- 第七节:模版结构优化
- 第八节:加载静态文件
- 第四章:数据库
- 第一节:MySQL相关软件
- 第二节:数据库操作
- 第三节:ORM模型
- 第四节:模型常用字段
- 第五节:外键和表关系
- 第六节:增删改查操作
- 第七节:查询操作
- 第八节:QuerySet API
- 第九节:ORM模型迁移
- 第十节:ORM作业
- 第十一节:ORM作业参考答案
- 第十二节:Pycharm连接数据库
- 第五章:视图高级
- 第一节:限制请求method
- 第二节:页面重定向
- 第三节:HttpRequest对象
- 第四节:HttpResponse对象
- 第五节:生成CSV文件
- 第六节:类视图
- 第七节:错误处理
- 第六章:表单
- 第一节:表单概述
- 第二节:用表单验证数据
- 第三节:ModelForm
- 第四节:文件上传
- 第七章:cookie和session
- 第八章:上下文处理器和中间件
- 第一节:上下文处理器
- 第二节:中间件
- 第九章:安全
- 第一节:CSRF攻击
- 第二节:XSS攻击
- 第三节:点击劫持攻击
- 第四节:SQL注入
- 第十章:信号
- 第一节:什么是信号
- 第十一章:验证和授权
- 第一节:概述
- 第二节:用户对象
- 第三节:权限和分组
- 第十二章:Admin系统
- 第十三章:Django的缓存
- 第十四章:memcached
- 第十五章:Redis