# 第二節:XSS攻擊
# XSS攻擊
XSS(Cross Site Script)攻擊又叫做跨站腳本攻擊。他的原理是用戶在使用具有`XSS`漏洞的網站的時候,向這個網站提交一些惡意的代碼,當用戶在訪問這個網站的某個頁面的時候,這個惡意的代碼就會被執行,從而來破壞網頁的結構,獲取用戶的隱私信息等。
## XSS攻擊場景:
比如`A網站`有一個發布帖子的入口,如果用戶在提交數據的時候,提交了一段`js`代碼比如:`<script>alert("hello world");</script>`,然后`A網站`在渲染這個帖子的時候,直接把這個代碼渲染了,那么這個代碼就會執行,會在瀏覽器的窗口中彈出一個模態對話框來顯示`hello world`!如果攻擊者能成功的運行以上這么一段`js`代碼,那他能做的事情就有很多很多了!
## XSS攻擊防御:
1. 如果不需要顯示一些富文本,那么在渲染用戶提交的數據的時候,直接進行轉義就可以了。在`Django`的模板中默認就是轉義的。也可以把數據在存儲到數據庫之前,就轉義再存儲進去,這樣以后在渲染的時候,即使不轉義也不會有安全問題,示例代碼如下:
```
<pre class="calibre12">```
<span class="hljs-keyword">from</span> django.template.defaultfilters <span class="hljs-keyword">import</span> escape
<span class="hljs-keyword">from</span> .models <span class="hljs-keyword">import</span> Comment
<span class="hljs-keyword">from</span> django.http <span class="hljs-keyword">import</span> HttpResponse
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">comment</span><span class="hljs-params">(request)</span>:</span>
content = request.POST.get(<span class="hljs-string">"content"</span>)
escaped_content = escape(content)
Comment.objects.create(content=escaped_content)
<span class="hljs-keyword">return</span> HttpResponse(<span class="hljs-string">'success'</span>)
```
```
2. 如果對于用戶提交上來的數據包含了一些富文本(比如:給字體換色,字體加粗等),那么這時候我們在渲染的時候也要以富文本的形式進行渲染,也即需要使用`safe`過濾器將其標記為安全的,這樣才能顯示出富文本樣式。但是這樣又會存在一個問題,如果用戶提交上來的數據存在攻擊的代碼呢,那將其標記為安全的肯定是有問題的。示例代碼如下:
```
<pre class="calibre12">```
<span class="hljs-title"># views.py</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">index</span><span class="hljs-params">(request)</span>:</span>
message = <span class="hljs-string">"<span style='color:red;'>紅色字體</span><script>alert('hello world');</script>"</span>;
<span class="hljs-keyword">return</span> render_template(request,<span class="hljs-string">'index.html'</span>,context={<span class="hljs-string">"message"</span>:message})
```
```
```
<pre class="calibre12">```
# index.html
```
```
那么這時候該怎么辦呢?這時候我們可以指定某些標簽我們是需要的(比如:span標簽),而某些標簽我們是不需要的(比如:script)那么我們在服務器處理數據的時候,就可以將這些需要的標簽保留下來,把那些不需要的標簽進行轉義,或者干脆移除掉,這樣就可以解決我們的問題了。這個方法是可行的,包括很多線上網站也是這樣做的,在`Python`中,有一個庫可以專門用來處理這個事情,那就是`sanitizer`。接下來講下這個庫的使用。
## `bleach`庫:
`bleach`庫是用來清理包含`html`格式字符串的庫。他可以指定哪些標簽需要保留,哪些標簽是需要過濾掉的。也可以指定標簽上哪些屬性是可以保留,哪些屬性是不需要的。想要使用這個庫,可以通過以下命令進行安裝:
```
<pre class="calibre12">```
pip install bleach
```
```
這個庫最重要的一個方法是`bleach.clean`方法,`bleach.clean`示例代碼如下:
```
<pre class="calibre12">```
<span class="hljs-keyword">import</span> bleach
<span class="hljs-keyword">from</span> bleach.sanitizer <span class="hljs-keyword">import</span> ALLOWED_TAGS,ALLOWED_ATTRIBUTES
<span class="hljs-class">@require_http_methods(['POST'])</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">message</span><span class="hljs-params">(request)</span>:</span>
<span class="hljs-title"># 從客戶端中獲取提交的數據</span>
content = request.POST.get(<span class="hljs-string">'content'</span>)
<span class="hljs-title"># 在默認的允許標簽中添加img標簽</span>
tags = ALLOWED_TAGS + [<span class="hljs-string">'img'</span>]
<span class="hljs-title"># 在默認的允許屬性中添加src屬性</span>
attributes = {**ALLOWED_ATTRIBUTES,<span class="hljs-string">'img'</span>:[<span class="hljs-string">'src'</span>]}
<span class="hljs-title"># 對提交的數據進行過濾</span>
cleaned_content=bleach.clean(content,tags=tags,attributes=attributes)
<span class="hljs-title"># 保存到數據庫中</span>
Message.objects.create(content=cleaned_content)
<span class="hljs-keyword">return</span> redirect(reverse(<span class="hljs-string">'index'</span>))
```
```
相關介紹如下:
1. `tags`:表示允許哪些標簽。
2. `attributes`:表示標簽中允許哪些屬性。
3. `ALLOWED_TAGS`:這個變量是`bleach`默認定義的一些標簽。如果不符合要求,可以對其進行增加或者刪除。
4. `ALLOWED_ATTRIBUTES`:這個變量是`bleach`默認定義的一些屬性。如果不符合要求,可以對其進行增加或者刪除。
### bleach更多資料:
1. github地址: <https://github.com/mozilla/bleach>
2. 文檔地址: <https://bleach.readthedocs.io/>
- 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