Django Web 應用安全
保護使用者資料是任何網站設計中不可或缺的一部分。我們之前在文章Web 安全性中解釋了一些常見的安全威脅——本文將透過實際演示說明 Django 的內建保護機制如何處理這些威脅。
| 先決條件 | 閱讀伺服器端程式設計的“網站安全性”主題。完成 Django 教程主題,至少到(包括)Django 教程第 9 部分:使用表單。 |
|---|---|
| 目標 | 瞭解為了保護 Django Web 應用程式的安全,您需要執行(或不執行)的主要操作。 |
概述
網站安全性主題概述了網站安全性對伺服器端設計意味著什麼,以及您應該防範的一些常見威脅。該文章的關鍵資訊之一是,幾乎所有攻擊在 Web 應用程式信任來自瀏覽器的的資料時都會成功。
警告:關於網站安全,您能學到的最重要的一課就是永遠不要信任來自瀏覽器的的資料。這包括 URL 引數中的 GET 請求資料、POST 資料、HTTP 標頭和 Cookie、使用者上傳的檔案等。始終檢查和清理所有傳入資料。始終假設最壞的情況。
對於 Django 使用者來說,好訊息是框架處理了許多常見的威脅!Django 中的安全性(Django 文件)文章解釋了 Django 的安全功能以及如何保護 Django 驅動的網站。
常見威脅/防護措施
本文不會重複 Django 文件中的內容,而是會在我們 Django 本地圖書館 教程的上下文中演示一些安全功能。
跨站指令碼 (XSS)
XSS 是一個術語,用於描述一類攻擊,這些攻擊允許攻擊者透過網站將客戶端指令碼注入到其他使用者的瀏覽器中。這通常是透過將惡意指令碼儲存在資料庫中來實現的,這些指令碼可以被檢索並顯示給其他使用者,或者透過讓使用者點選一個連結來執行,該連結會導致使用者的瀏覽器執行攻擊者的 JavaScript 程式碼。
Django 的模板系統透過轉義 HTML 中“危險”的特定字元來防止大多數 XSS 攻擊。我們可以嘗試將一些 JavaScript 程式碼注入到我們的 LocalLibrary 網站中來演示這一點,方法是使用我們在Django 教程第 9 部分:使用表單中設定的建立作者表單。
- 使用開發伺服器啟動網站(
python3 manage.py runserver)。 - 在本地瀏覽器中開啟網站,並登入到您的超級使用者帳戶。
- 導航到作者建立頁面(URL 應為:
http://127.0.0.1:8000/catalog/author/create/)。 - 輸入新使用者的姓名和日期詳細資訊,然後將以下文字附加到“姓氏”欄位:
<script>alert('Test alert');</script>。
注意:這是一個無害的指令碼,如果執行,它將在您的瀏覽器中顯示一個警報框。如果在您提交記錄時顯示了警報,則表示該網站容易受到 XSS 威脅。
- 按提交儲存記錄。
- 儲存作者後,將顯示如下所示。由於 XSS 保護,
alert()不會執行。相反,指令碼將顯示為純文字。
如果檢視頁面 HTML 原始碼,您會發現指令碼標籤的危險字元已轉換為其無害的轉義程式碼等效項(例如,> 現在為 >)。
<h1>
Author: Boon<script>alert('Test alert');</script>, David
(Boonie)
</h1>
使用 Django 模板可以防止大多數 XSS 攻擊。但是,可以關閉此保護,並且該保護不會自動應用於所有通常不會由使用者輸入填充的標籤(例如,表單欄位中的 help_text 通常不是使用者提供的,因此 Django 不會轉義這些值)。
XSS 攻擊也可能源自其他不受信任的資料來源,例如 Cookie、Web 服務或上傳的檔案(只要資料在包含在頁面之前沒有得到充分清理)。如果要顯示來自這些來源的資料,則可能需要新增自己的清理程式碼。
跨站請求偽造 (CSRF) 保護
CSRF 攻擊允許惡意使用者在未經使用者知情或同意的情況下,使用其他使用者的憑據執行操作。例如,考慮我們有一個駭客想要為我們的 LocalLibrary 建立更多作者的情況。
注意:顯然,我們的駭客並非為了錢!更有野心的駭客可以在其他網站上使用相同的方法執行更具破壞性的任務(例如,將資金轉入自己的帳戶等)。
為了做到這一點,他們可能會建立一個如下所示的 HTML 檔案,其中包含一個作者建立表單(類似於我們在上一節中使用的表單),該表單在檔案載入後立即提交。然後,他們會將該檔案傳送給所有圖書管理員,並建議他們開啟該檔案(它包含一些無害的資訊,真的!)。如果任何登入的圖書管理員打開了該檔案,則表單將使用其憑據提交,並且將建立一個新的作者。
<html lang="en">
<body onload="document.EvilForm.submit()">
<form
action="http://127.0.0.1:8000/catalog/author/create/"
method="post"
name="EvilForm">
<table>
<tr>
<th><label for="id_first_name">First name:</label></th>
<td>
<input
id="id_first_name"
maxlength="100"
name="first_name"
type="text"
value="Mad"
required />
</td>
</tr>
<tr>
<th><label for="id_last_name">Last name:</label></th>
<td>
<input
id="id_last_name"
maxlength="100"
name="last_name"
type="text"
value="Man"
required />
</td>
</tr>
<tr>
<th><label for="id_date_of_birth">Date of birth:</label></th>
<td>
<input id="id_date_of_birth" name="date_of_birth" type="text" />
</td>
</tr>
<tr>
<th><label for="id_date_of_death">Died:</label></th>
<td>
<input
id="id_date_of_death"
name="date_of_death"
type="text"
value="12/10/2016" />
</td>
</tr>
</table>
<input type="submit" value="Submit" />
</form>
</body>
</html>
執行開發 Web 伺服器,並使用您的超級使用者帳戶登入。將上面的文字複製到一個檔案中,然後在瀏覽器中開啟它。您應該會收到一個 CSRF 錯誤,因為 Django 對此類情況有保護措施!
啟用保護的方式是在表單定義中包含 {% csrf_token %} 模板標籤。然後,此標記將在您的 HTML 中呈現如下所示,其值為當前瀏覽器中特定使用者的特定值。
<input
type="hidden"
name="csrfmiddlewaretoken"
value="0QRWHnYVg776y2l66mcvZqp8alrv4lb8S8lZ4ZJUWGZFA5VHrVfL2mpH29YZ39PW" />
Django 生成一個特定於使用者/瀏覽器的金鑰,並將拒絕不包含該欄位或包含錯誤欄位值的表單(針對特定使用者/瀏覽器)。
要使用這種型別的攻擊,駭客現在必須發現幷包含特定目標使用者的 CSRF 金鑰。他們也不能使用向所有圖書管理員傳送惡意檔案並希望其中一人開啟它的“散彈槍”方法,因為 CSRF 金鑰是特定於瀏覽器的。
Django 的 CSRF 保護預設情況下處於啟用狀態。您應該始終在表單中使用 {% csrf_token %} 模板標籤,並對可能更改或向資料庫新增資料的請求使用 POST 方法。
其他保護措施
Django 還提供其他形式的保護(其中大多數很難或不值得特別演示)
- SQL 注入保護
-
SQL 注入漏洞使惡意使用者能夠在資料庫上執行任意 SQL 程式碼,從而允許訪問、修改或刪除資料,而不管使用者的許可權如何。在幾乎所有情況下,您都將使用 Django 的查詢集/模型訪問資料庫,因此生成的 SQL 將由底層資料庫驅動程式正確轉義。如果您確實需要編寫原始查詢或自定義 SQL,則需要明確考慮防止 SQL 注入。
- 點選劫持保護
-
在此攻擊中,惡意使用者劫持了旨在用於可見頂級站點的點選,並將它們路由到下面的隱藏頁面。例如,此技術可能用於顯示合法的銀行網站,但在攻擊者控制的不可見的
<iframe>中捕獲登入憑據。Django 以點選劫持保護的形式包含X-Frame-Options中介軟體,該中介軟體在支援的瀏覽器中可以防止站點在框架內呈現。 - 強制執行 TLS/HTTPS
-
可以在 Web 伺服器上啟用 TLS/HTTPS,以加密站點和瀏覽器之間所有流量,包括否則將以明文傳送的身份驗證憑據(強烈建議啟用 HTTPS)。如果啟用了 HTTPS,則 Django 提供了一些其他保護措施,您可以使用它們
SECURE_PROXY_SSL_HEADER可用於檢查內容是否安全,即使它來自非 HTTP 代理。SECURE_SSL_REDIRECT用於將所有 HTTP 請求重定向到 HTTPS。- 使用HTTP 嚴格傳輸安全 (HSTS)。這是一個 HTTP 標頭,它通知瀏覽器所有將來對特定站點的連線都應始終使用 HTTPS。結合將 HTTP 請求重定向到 HTTPS,此設定可確保在成功連線後始終使用 HTTPS。HSTS 可以使用
SECURE_HSTS_SECONDS和SECURE_HSTS_INCLUDE_SUBDOMAINS或在 Web 伺服器上進行配置。 - 透過將
SESSION_COOKIE_SECURE和CSRF_COOKIE_SECURE設定為True來使用“安全”Cookie。這將確保 Cookie 僅透過 HTTPS 傳送。
- 主機頭驗證
-
使用
ALLOWED_HOSTS僅接受來自受信任主機的請求。
還有許多其他保護措施,以及上述機制的使用注意事項。雖然我們希望這能為您提供 Django 提供的功能概述,但您仍應閱讀 Django 安全文件。
總結
Django 對許多常見威脅(包括 XSS 和 CSRF 攻擊)具有有效的保護措施。在本文中,我們演示了 Django 在我們的 LocalLibrary 網站中如何處理這些特定威脅。我們還簡要概述了一些其他保護措施。
這只是對 Web 安全性的一個非常簡短的介紹。我們強烈建議您閱讀Django 中的安全性 以獲得更深入的瞭解。
本模組關於 Django 的最後一個步驟是完成評估任務。
另請參閱
- Django 中的安全性(Django 文件)
- Web 上的安全性(MDN)
- 安全實踐實施指南(MDN)