# 第一節: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