網站安全
網站安全需要在網站設計和使用的各個方面保持警惕。本文不會讓你成為網站安全專家,但它將幫助你瞭解威脅來自哪裡,以及你可以採取哪些措施來加強你的 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 語句將'字元視為字串文字的開頭和結尾。透過在該字元前面放置反斜槓(\'),我們轉義了該符號,並告訴 SQL 將其視為字元(只是字串的一部分)。
在以下語句中,我們轉義了'字元。SQL 現在將名稱解釋為粗體中的整個字串(這確實是一個非常奇怪的名稱,但沒有害處)。
SELECT * FROM users WHERE name = 'a\';DROP TABLE users; SELECT * FROM userinfo WHERE \'t\' = \'t';
Web 框架通常會為你處理字元轉義。例如,Django 確保傳遞給查詢集(模型查詢)的任何使用者資料都已轉義。
注意:本節大量借鑑了此處維基百科中的資訊。
跨站請求偽造 (CSRF)
CSRF 攻擊允許惡意使用者在未經使用者知情或同意的情況下,使用其他使用者的憑據執行操作。
這種型別的攻擊最好透過示例來解釋。Josh 是一位惡意使用者,他知道某個特定站點允許已登入的使用者使用包含帳戶名稱和金額的 HTTPPOST請求向指定帳戶傳送資金。Josh 建立了一個表單,其中包含他的銀行詳細資訊和金額作為隱藏欄位,並將其透過電子郵件傳送給其他站點使用者(提交按鈕偽裝成指向“快速致富”站點的連結)。
如果使用者點選提交按鈕,則會向伺服器傳送一個包含交易詳細資訊以及瀏覽器與站點關聯的任何客戶端 Cookie 的 HTTPPOST請求(將關聯的站點 Cookie 新增到請求是正常的瀏覽器行為)。伺服器將檢查 Cookie,並使用它們來確定使用者是否已登入並是否有權進行交易。
結果是,任何在登入到交易站點時點選提交按鈕的使用者都將進行交易。Josh 發財了。
注意:這裡的技巧是 Josh 不需要訪問使用者的 Cookie(或訪問憑據)。使用者的瀏覽器儲存此資訊,並自動將其包含在傳送到關聯伺服器的所有請求中。
防止此類攻擊的一種方法是伺服器要求POST請求包含使用者特定的站點生成的金鑰。金鑰將在傳送用於進行轉賬的 Web 表單時由伺服器提供。此方法阻止 Josh 建立自己的表單,因為他必須知道伺服器為使用者提供的金鑰。即使他發現了金鑰併為特定使用者建立了一個表單,他也將無法再使用相同的表單來攻擊每個使用者。
Web 框架通常包含此類 CSRF 防護機制。
其他威脅
其他常見的攻擊/漏洞包括
- 點選劫持。在此攻擊中,惡意使用者劫持了原本打算用於可見頂級站點的點選,並將它們路由到隱藏在下方的一個頁面。例如,此技術可能用於顯示合法的銀行站點,但將登入憑據捕獲到攻擊者控制的不可見的
<iframe>中。點選劫持還可用於讓使用者點選可見站點上的按鈕,但在這樣做時實際上無意中點選了完全不同的按鈕。作為防禦措施,你的站點可以透過設定適當的 HTTP 標頭來防止自己被嵌入到另一個站點的 iframe 中。 - 拒絕服務 (DoS)。DoS 通常透過向目標站點發送大量虛假請求來實現,從而使合法使用者無法訪問該站點。這些請求可能數量眾多,或者每個請求都可能消耗大量資源(例如,緩慢讀取或上傳大型檔案)。DoS 防禦通常透過識別和阻止“不良”流量,同時允許合法訊息透過來工作。這些防禦措施通常位於 Web 伺服器之前或內部(它們不是 Web 應用程式本身的一部分)。
- 目錄遍歷 (檔案和資訊洩露)。在這種攻擊中,惡意使用者試圖訪問他們不應該能夠訪問的 Web 伺服器檔案系統的一部分。當用戶能夠傳遞包含檔案系統導航字元(例如,
../../)的檔名時,就會發生此漏洞。解決方法是在使用輸入之前對其進行清理。 - 檔案包含。在這種攻擊中,使用者能夠指定一個“意外”檔案,以便在傳遞給伺服器的資料中顯示或執行。載入後,此檔案可能會在 Web 伺服器或客戶端上執行(導致 XSS 攻擊)。解決方法是在使用輸入之前對其進行清理。
- 命令注入。命令注入攻擊允許惡意使用者在主機作業系統上執行任意系統命令。解決方法是在系統呼叫中使用使用者輸入之前對其進行清理。
有關網站安全威脅的全面列表,請參閱 分類:Web 安全漏洞利用(維基百科)和 分類:攻擊(開放 Web 應用程式安全專案)。
一些關鍵資訊
前面各節中幾乎所有安全漏洞利用都可以在 Web 應用程式信任來自瀏覽器的資料時成功。無論您採取其他什麼措施來提高網站的安全性,您都應在將使用者源資料顯示在瀏覽器中、用於 SQL 查詢或傳遞給作業系統或檔案系統呼叫之前對其進行清理。
警告:關於網站安全,您可以學到的最重要的課程是**永遠不要信任來自瀏覽器的資料**。這包括但不限於GET請求的 URL 引數、POST請求、HTTP 標頭和 Cookie 以及使用者上傳的檔案中的資料。始終檢查和清理所有傳入資料。始終假設最壞的情況。
您可以採取的其他一些具體措施是
- 使用更有效的密碼管理。鼓勵使用強密碼。考慮為您的網站啟用雙因素身份驗證,以便除了密碼之外,使用者還必須輸入另一個身份驗證程式碼(通常是透過某些僅使用者擁有的物理硬體傳遞的程式碼,例如傳送到其手機的簡訊中的程式碼)。
- 配置您的 Web 伺服器以使用 HTTPS 和 HTTP 嚴格傳輸安全 (HSTS)。HTTPS 對客戶端和伺服器之間傳送的資料進行加密。這確保登入憑據、Cookie、
POST請求資料和標頭資訊不容易被攻擊者獲取。 - 跟蹤最流行的威脅(當前 OWASP 列表在此處)並首先解決最常見的漏洞。
- 使用 漏洞掃描工具 對您的網站執行自動化安全測試。稍後,您非常成功的網站還可以透過提供錯誤賞金來查詢錯誤 Mozilla 在此處提供錯誤賞金。
- 僅儲存和顯示您需要的資料。例如,如果您的使用者必須儲存諸如信用卡詳細資訊之類的敏感資訊,則僅顯示使用者可以識別信用卡號的足夠部分,而不是可以被攻擊者複製並在另一個站點上使用的足夠部分。目前最常見的模式是僅顯示信用卡號的後 4 位數字。
Web 框架可以幫助緩解許多更常見的漏洞。
總結
本文解釋了 Web 安全的概念以及您的網站應嘗試防禦的一些更常見的威脅。最重要的是,您應該瞭解 Web 應用程式不能信任來自 Web 瀏覽器的任何資料。所有使用者資料都應在顯示或用於 SQL 查詢和檔案系統呼叫之前進行清理。
透過本文,您已經完成了 本模組,涵蓋了您在伺服器端網站程式設計中的第一步。我們希望您喜歡學習這些基本概念,並且您現在已準備好選擇一個 Web 框架並開始程式設計。