網站安全
網站安全需要對網站設計和使用的各個方面保持警惕。這篇入門文章不會讓你成為網站安全專家,但它將幫助你瞭解威脅來自何處,以及你可以做些什麼來增強你的 Web 應用程式,以抵禦最常見的攻擊。
| 預備知識 | 基本的計算機知識。 |
|---|---|
| 目標 | 瞭解 Web 應用程式安全最常見的威脅,以及你可以採取哪些措施來降低網站被駭客攻擊的風險。 |
什麼是網站安全?
網際網路是一個危險的地方!我們經常聽到網站因拒絕服務攻擊而無法訪問,或者其主頁上顯示修改過的(通常具有破壞性的)資訊。在其他引人注目的案例中,數百萬個密碼、電子郵件地址和信用卡詳細資訊被洩露到公共領域,使網站使用者面臨個人尷尬和財務風險。
網站安全的目的就是防止這些(或任何)型別的攻擊。網站安全更正式的定義是保護網站免受未經授權的訪問、使用、修改、銷燬或中斷的行為/實踐。
有效的網站安全需要在整個網站設計中付出努力:包括你的 Web 應用程式、Web 伺服器的配置、建立和續訂密碼的策略以及客戶端程式碼。雖然所有這些聽起來都很可怕,但好訊息是,如果你正在使用伺服器端 Web 框架,它幾乎肯定會“預設”啟用針對許多常見攻擊的健壯且經過深思熟慮的防禦機制。其他攻擊可以透過你的 Web 伺服器配置來緩解,例如透過啟用 HTTPS。最後,還有公開可用的漏洞掃描工具,可以幫助你找出是否犯了任何明顯的錯誤。
本文的其餘部分將為你提供有關一些常見威脅以及你可以採取的一些簡單步驟來保護你的網站的更多詳細資訊。
注意:這是一個入門主題,旨在幫助你開始思考網站安全,但它並不詳盡。
網站安全威脅
本節列舉了一些最常見的網站威脅以及如何緩解它們。閱讀時請注意,當 Web 應用程式信任或對來自瀏覽器的資料不夠“偏執”時,威脅最容易成功。
跨站指令碼 (XSS)
XSS 是一個術語,用於描述一類攻擊,它允許攻擊者透過網站將客戶端指令碼注入到其他使用者的瀏覽器中。由於注入的程式碼是從網站傳送到瀏覽器的,因此該程式碼被信任,可以執行諸如將使用者的網站授權 cookie 傳送給攻擊者之類的操作。當攻擊者獲得 cookie 後,他們就可以像使用者一樣登入網站,並執行使用者可以執行的任何操作,例如訪問他們的信用卡詳細資訊、檢視聯絡資訊或更改密碼。
注意:XSS 漏洞在歷史上比任何其他型別的安全威脅都更常見。
XSS 漏洞根據網站將注入指令碼返回到瀏覽器的方式分為反射型和持久型。
- 反射型 XSS 漏洞發生在使用者內容傳遞到伺服器後立即且未經修改地返回並在瀏覽器中顯示時。原始使用者內容中的任何指令碼都會在新頁面載入時執行。例如,考慮一個網站搜尋功能,其中搜索詞被編碼為 URL 引數,並且這些詞與結果一起顯示。攻擊者可以構造一個包含惡意指令碼作為引數的搜尋連結(例如,
https://mdn.club.tw?q=beer<script%20src="http://example.com/tricky.js"></script>),並將其透過電子郵件傳送給其他使用者。如果目標使用者點選這個“有趣的連結”,指令碼將在顯示搜尋結果時執行。如前所述,這會為攻擊者提供以目標使用者身份進入網站所需的所有資訊,可能以使用者身份進行購買或共享其聯絡資訊。 - 持久型 XSS 漏洞發生在惡意指令碼儲存在網站上,然後稍後未經修改地重新顯示給其他使用者無意中執行時。例如,一個接受包含未經修改的 HTML 評論的論壇可以儲存來自攻擊者的惡意指令碼。當評論顯示時,指令碼會執行,並將訪問使用者帳戶所需的資訊傳送給攻擊者。這種攻擊非常流行且強大,因為攻擊者甚至可能不需要與受害者進行任何直接接觸。
雖然來自 POST 或 GET 請求的資料是 XSS 漏洞最常見的來源,但來自瀏覽器的任何資料都可能存在漏洞,例如由瀏覽器呈現的 cookie 資料,或上傳並顯示的使用者檔案。
抵禦 XSS 漏洞的最佳防禦措施是刪除或停用任何可能包含執行程式碼指令的標記。對於 HTML,這包括諸如 <script>、<object>、<embed> 和 <link> 等元素。
修改使用者資料,使其不能用於執行指令碼或以其他方式影響伺服器程式碼執行的過程稱為輸入消毒。許多 Web 框架預設會自動對 HTML 表單中的使用者輸入進行消毒。
SQL 注入
SQL 注入漏洞使惡意使用者能夠在資料庫上執行任意 SQL 程式碼,從而允許訪問、修改或刪除資料,而無論使用者許可權如何。成功的注入攻擊可能會偽造身份、建立具有管理許可權的新身份、訪問伺服器上的所有資料,或者銷燬/修改資料使其無法使用。
SQL 注入型別包括基於錯誤的 SQL 注入、基於布林錯誤的 SQL 注入和基於時間的 SQL 注入。
如果傳遞給底層 SQL 語句的使用者輸入可以改變語句的含義,則存在此漏洞。例如,以下程式碼旨在列出所有具有特定名稱(userName)的使用者,該名稱是從 HTML 表單提供的。
statement = "SELECT * FROM users WHERE name = '" + userName + "';"
如果使用者指定了一個真實名稱,該語句將按預期工作。但是,惡意使用者可以透過為 userName 指定 a';DROP TABLE users; SELECT * FROM userinfo WHERE 't' = 't 來完全改變此 SQL 語句的行為,使其變為以下示例中的新語句。
SELECT * FROM users WHERE name = 'a';DROP TABLE users; SELECT * FROM userinfo WHERE 't' = 't';
修改後的語句建立了一個有效的 SQL 語句,該語句刪除了 users 表並從 userinfo 表中選擇了所有資料(這會洩露每個使用者的資訊)。這之所以有效,是因為注入文字的第一部分(a';)完成了原始語句。
為了避免此類攻擊,最佳實踐是使用引數化查詢(預處理語句)。這種方法確保使用者輸入被視為資料字串而不是可執行的 SQL,因此使用者不能濫用特殊的 SQL 語法字元來生成意外的 SQL 語句。以下是一個示例:
SELECT * FROM users WHERE name = ? AND password = ?;
例如,在 Python 中執行上述查詢時,我們將 name 和 password 作為引數傳遞,如下所示。
cursor.execute("SELECT * FROM users WHERE name = ? AND password = ?", (name, password))
庫通常提供抽象良好的 API,為開發人員處理 SQL 注入保護,例如 Django 的模型。你可以透過使用封裝的 API 而不是直接編寫原始 SQL 來避免 SQL 注入。
跨站請求偽造 (CSRF)
CSRF 攻擊允許惡意使用者在其他使用者不知情或未經其同意的情況下,使用該使用者的憑據執行操作。
這類攻擊最好透過示例來解釋。Josh 是一個惡意使用者,他知道某個特定網站允許登入使用者使用包含賬戶名和金額的 HTTP POST 請求向指定賬戶匯款。Josh 構建了一個表單,其中包含他的銀行詳細資訊和金額作為隱藏欄位,並透過電子郵件將其傳送給其他網站使用者(“提交”按鈕偽裝成指向“快速致富”網站的連結)。
如果使用者點選提交按鈕,一個 HTTP POST 請求將被髮送到伺服器,其中包含交易詳情和瀏覽器與網站關聯的任何客戶端 Cookie(將關聯的網站 Cookie 新增到請求中是正常的瀏覽器行為)。伺服器將檢查 Cookie,並使用它們來確定使用者是否已登入以及是否具有進行交易的許可權。
結果是,任何在登入交易網站時點選“提交”按鈕的使用者都將進行交易。Josh 因此變得富有。
注意:這裡的訣竅是 Josh 不需要訪問使用者的 Cookie(或訪問憑據)。使用者的瀏覽器儲存此資訊並自動將其包含在傳送到關聯伺服器的所有請求中。
防止此類攻擊的一種方法是,伺服器要求 POST 請求包含一個使用者特定的、由網站生成的秘密。該秘密將在傳送用於進行轉賬的網頁表單時由伺服器提供。這種方法阻止了 Josh 建立自己的表單,因為他必須知道伺服器為使用者提供的秘密。即使他找到了秘密併為特定使用者建立了表單,他也無法再使用相同的表單攻擊所有使用者。
Web 框架通常包含此類 CSRF 防護機制。
其他威脅
其他常見的攻擊/漏洞包括:
- 點選劫持 (Clickjacking)。在這種攻擊中,惡意使用者劫持了旨在可見的頂級站點的點選,並將其路由到下方的隱藏頁面。例如,此技術可能用於顯示一個合法的銀行網站,但將登入憑據捕獲到由攻擊者控制的不可見的
<iframe>中。點選劫持還可能用於讓使用者點選可見網站上的一個按鈕,但實際上卻無意中點選了一個完全不同的按鈕。作為防禦措施,你的網站可以透過設定適當的 HTTP 頭來阻止自身被嵌入到其他網站的 iframe 中。 - 拒絕服務 (DoS)。DoS 通常透過向目標網站傳送大量虛假請求來實現,從而中斷合法使用者對網站的訪問。請求可能數量眾多,或者它們可能單獨消耗大量資源(例如,慢速讀取或上傳大檔案)。DoS 防禦通常透過識別和阻止“惡意”流量,同時允許合法訊息透過來實現。這些防禦措施通常位於 Web 伺服器之前或內部(它們不是 Web 應用程式本身的一部分)。
- 目錄遍歷 (Directory Traversal)(檔案和洩露)。在這種攻擊中,惡意使用者試圖訪問他們不應訪問的 Web 伺服器檔案系統部分。當用戶能夠傳遞包含檔案系統導航字元(例如,
../../)的檔名時,就會出現此漏洞。解決方案是在使用輸入之前對其進行消毒。 - 檔案包含 (File Inclusion)。在這種攻擊中,使用者能夠指定一個“非預期”檔案,以便在傳遞給伺服器的資料中顯示或執行。載入時,此檔案可能會在 Web 伺服器或客戶端執行(導致 XSS 攻擊)。解決方案是在使用輸入之前對其進行消毒。
- 命令注入 (Command Injection)。命令注入攻擊允許惡意使用者在主機作業系統上執行任意系統命令。解決方案是在使用者輸入可能用於系統呼叫之前對其進行消毒。
有關網站安全威脅的完整列表,請參閱類別:Web 安全漏洞 (Wikipedia) 和類別:攻擊 (開放式 Web 應用程式安全專案)。
幾個關鍵資訊
上一節中幾乎所有的安全漏洞都是在 Web 應用程式信任來自瀏覽器的資料時成功的。無論你採取什麼其他措施來提高網站的安全性,都應該在將所有使用者生成的資料顯示在瀏覽器中、用於 SQL 查詢或傳遞給作業系統或檔案系統呼叫之前對其進行消毒。
警告:關於網站安全,你可以學到的最重要的一課是永遠不要信任來自瀏覽器的資料。這包括但不限於 GET 請求的 URL 引數、POST 請求、HTTP 標頭和 Cookie 中的資料,以及使用者上傳的檔案。始終檢查並消毒所有傳入資料。始終假設最壞的情況。
你可以採取的其他具體步驟包括:
- 使用更有效的密碼管理。鼓勵使用強密碼。考慮為你的網站啟用雙重身份驗證,除了密碼之外,使用者還必須輸入另一個身份驗證程式碼(通常是透過使用者獨有的物理硬體傳遞的程式碼,例如傳送到其手機的簡訊中的程式碼)。
- 配置你的 Web 伺服器以使用 HTTPS 和 HTTP 嚴格傳輸安全 (HSTS)。HTTPS 會加密客戶端和伺服器之間傳送的資料。這確保登入憑據、Cookie、
POST請求資料和標頭資訊不容易被攻擊者獲取。 - 跟蹤最常見的威脅(當前的 OWASP 列表在這裡)並首先解決最常見的漏洞。
- 使用漏洞掃描工具對你的網站執行自動化安全測試。之後,你非常成功的網站也可能透過提供錯誤賞金來發現錯誤,就像 Mozilla 在這裡所做的那樣。
- 只儲存和顯示你需要的資料。例如,如果你的使用者必須儲存信用卡詳細資訊等敏感資訊,則只顯示足夠卡號以供使用者識別,但又不足以被攻擊者複製並在其他網站上使用。目前最常見的模式是隻顯示信用卡號的最後 4 位數字。
- 保持軟體更新。大多數伺服器都有定期的安全更新,可以修復或緩解已知的漏洞。如果可能,安排定期的自動化更新,最好在網站流量最少的時候安排更新。最好在更新前備份資料並測試新的軟體版本,以確保伺服器上沒有相容性問題。
Web 框架可以幫助緩解許多常見的漏洞。
總結
本文解釋了網路安全的概念以及您的網站應嘗試防禦的一些常見威脅。最重要的是,您應該明白,Web 應用程式不能信任來自 Web 瀏覽器的任何資料。所有使用者資料都應該在顯示、用於 SQL 查詢和檔案系統呼叫之前進行清理。
透過本文,您已完成本模組,涵蓋了伺服器端網站程式設計的入門步驟。我們希望您喜歡學習這些基本概念,現在您已準備好選擇一個 Web 框架並開始程式設計。