MSDN 首頁 

建置安全的 ASP.NET 網頁和控制項

發佈日期: 2004 年 5 月 28 日
本頁內容
本單元內容本單元內容
目標目標
適用於適用於
如何使用本單元如何使用本單元
潛在威脅及因應對策潛在威脅及因應對策
設計考量設計考量
輸入驗證輸入驗證
跨網站指令碼跨網站指令碼
驗證驗證
授權授權
模擬模擬
機密資料機密資料
工作階段管理工作階段管理
參數操作參數操作
例外管理例外管理
稽核和記錄稽核和記錄
總結總結
其他資源其他資源

本單元內容

網頁和控制項是在應用程式的防禦最前線,容易受到意圖破壞應用程式安全性的攻擊者密切探測。這些攻擊的最終目標通常是後端系統和資料存放區。

成功的應用程式攻擊,例如程式碼注入或跨網站指令碼 (Cross-Site Scripting,XSS),會利用伺服器端應用程式的弱點造成極大的破壞力,並導致資訊洩露、偽造識別身份、權限提升及遠端程式碼執行。若要建立安全的網頁和控制項,您必須遵循本單元所討論的正確程式設計準則。

本單元一開始即列出常見的 ASP.NET 網頁和控制項潛在威脅及相關因應對策,並加以說明。接下來是一份必須提出的應用程式安全性區域之完整清單。這包括輸入驗證、輸出編碼、驗證、授權、模擬、機密資料保護、安全工作階段管理、參數操作保護和例外管理。這些技術是深度安全解決方案的基本防禦部份。上述潛在威脅經常遭到忽視,使得攻擊者能夠順利破壞系統,就算有多麼穩固的基礎結構也一樣。

回到頁首回到頁首

目標

透過本單元即可:

設計安全的 ASP.NET 網頁和控制項。

使用規則運算式和其他技術來研發安全的驗證程式碼。

跨網站指令碼 (XSS)。

驗證和授權使用者。

研發安全的表單驗證。

防止大量的例外詳細資料傳至用戶端。

管理和保障 ASP.NET 工作階段的安全。

防止參數操作。

知道套用哪些因應對策來解決一般潛在威脅,包括程式碼注入、連線劫持、偽造識別身份、參數操作、網路竊聽、資訊洩露、跨網站指令碼 (XSS) 和 Cookie 重新執行的攻擊。

回到頁首回到頁首

適用於

本單元適用於下列產品及技術:

Microsoft® Windows® 2000 Server 及 Microsoft Windows Server™ 2003

Microsoft .NET Framework 1.1 及 ASP.NET 1.1

回到頁首回到頁首

如何使用本單元

除了所描述的安全程式設計準則之外,請利用本指南的對應單元,幫助您建立安全的 ASP.NET 網頁和控制項。

請執行單元 19<保障 ASP.NET 應用程式及 Web 服務的安全>中的步驟。此單元幫助您以 Machine.config 和 Web.config 的安全設定適當地設定 ASP.NET。

請利用本指南的檢查清單一節所附的檢查清單。<檢查清單:保障 ASP.NET 的安全>結合本單元和單元 19 所提供的建議。確定您有實作其指引。

了解專門針對 ASP.NET 網頁和控制項的潛在威脅和攻擊。根據本單元的指引來套用因應對策。

請閱讀單元 4<設計安全 Web 應用程式的指導方針>。本單元 (單元 10) 的許多建議都是依據單元 4 所討論的設計指導方針。

架構設計師應該參考本單元的「設計考量」一節。

開發人員應該在開發過程中套用本單元的指導方針。開發人員必須特別留意輸入資料的驗證,因為大部份最高應用程式層級的攻擊都是仰賴本區域的弱點

請從程式設計的觀點了解控制項,以便對 ASP.NET 網頁和控制項的安全性做細部調整。

請使用應用程式弱點類別作為處理一般問題的方法。應用程式弱點類別提供有用的方式來處理問題並加以分組。

回到頁首回到頁首

潛在威脅及因應對策

大部份 Web 應用程式攻擊需要在 HTTP 要求內傳遞惡意的輸入。其一般目標是要迫使應用程式執行未授權的作業或干擾其正常作業。這足以說明徹底的輸入驗證對許多攻擊而言是重要的因應對策,當您在開發 ASP.NET 網頁和控制項時應該將它列為第一優先對象。最常見的潛在威脅包括:

程式碼注入

連線劫持

偽造識別身份

參數操作

網路竊聽

資訊洩露

[圖 10.1] 著重於 Web 應用程式最常見的潛在威脅。

ASP.NET 網頁和控制項的一般潛在威脅

[圖 10.1]
ASP.NET 網頁和控制項的一般潛在威脅和控制項

程式碼注入

當攻擊者使用應用程式的安全性內容而造成任意執行程式碼時,會發生程式碼注入。如果應用程式使用特殊權限帳戶執行,則風險升高。

攻擊

程式碼注入攻擊有許多不同類型。其中包含:

跨網站指令碼。惡意指令碼會傳送至 Web 應用程式作為輸入。然後再傳回至它執行所在的使用者瀏覽器。

緩衝區溢位。Managed 程式碼的字體驗證可大幅降低風險,但應用程式仍然有弱點,尤其是在呼叫 Unmanaged 程式碼的地方。緩衝區溢位讓攻擊者能夠在 Web 應用程式處理序內使用其安全性內容任意執行程式碼。

SQL 注入。此攻擊的目標為容易入侵的資料存取程式碼。攻擊者傳送會改變預定查詢或在資料庫中執行全新查詢的 SQL 輸入。表單驗證登入網頁是常見的目標,因為使用者名稱和密碼會用來查詢使用者存放區。

弱點

會導致成功的程式碼注入攻擊的弱點包括:

安全性不足的或遺漏的輸入驗證,或對用戶端輸入驗證的依賴

包括 HTML 輸出中的未驗證輸入

動態建構不使用型別參數的 SQL 陳述式

使用權限過高的處理序帳戶和資料庫登入

因應對策

下列因應對策可用來防止程式碼注入:

驗證輸入,使攻擊者無法注入指令碼或造成緩衝區溢位。

編碼包括輸入的所有輸出。這可防止潛在的惡意指令碼標籤被解譯為用戶端瀏覽器的程式碼。

使用接受參數的預存程序,以防止惡意 SQL 輸入被資料庫當作可執行的陳述式加以處理。

使用最小權限處理序和模擬帳戶。這樣可降低風險及減少攻擊者設法利用應用程式的安全性內容執行程式碼而造成的傷害。

連線劫持

連線劫持發生於攻擊者擷取驗證權杖及接管另一個使用者的工作階段時。驗證權杖通常是儲存在 Cookie 或 URL 中。如果攻擊者擷取驗證權杖,他可以連同要求一起將它傳給應用程式。應用程式會將此要求與合法使用者的工作階段相關聯,而讓攻擊者能夠存取應用程式需要驗證存取的受限制區域。然後攻擊者會採用合法使用者的識別身份和權限。

弱點

使網頁和控制項易發生連線劫持的常見弱點包括:

URL 中未受保護的工作階段識別元

混合個人化 Cookie 與驗證 Cookie

透過未加密連結而傳送的驗證 Cookie

攻擊

連線劫持攻擊包括:

Cookie 重新執行。攻擊者利用網路監視軟體或利用其他方式 (如利用 XSS 指令碼弱點) 來擷取驗證 Cookie。

查詢字串操作。惡意使用者會變更在 URL 查詢字串中明確顯示的工作階段識別元。

因應對策

您可以運用下列因應對策來防止發生連線劫持:

隔開個人化和驗證 Cookie。

僅透過 HTTPS 連線傳輸驗證 Cookie。

不要傳送工作階段識別元,它們代表查詢字串中的已驗證使用者。

在執行如下訂單、匯款等重要作業之前,請重新驗證使用者。

偽造識別身份

偽造識別身份發生於惡意使用者假裝合法使用者的識別身份而存取應用程式時。

弱點

使網頁和控制項容易發生偽造識別身份的欺騙攻擊的常見弱點包括:

透過未加密連結而傳送的驗證認證

透過未加密連結而傳送的驗證 Cookie

安全性不足的密碼和原則

使用者存放區中安全性不足的認證儲存

攻擊

偽造識別身份的欺騙攻擊包括:

Cookie 重新執行。攻擊者利用網路監視軟體或利用 XSS 攻擊來竊取驗證 Cookie。然後攻擊者將 Cookie 傳送至應用程式以詐騙存取權。

暴力式密碼攻擊。攻擊者重複嘗試使用者和密碼組合。

字典攻擊。在此自動的暴力式密碼攻擊中,會嘗試字典中的每一個字來猜測密碼。

因應對策

您可以運用下列因應對策來防止偽造識別身份:

僅透過 HTTPS 連線傳送驗證認證和 Cookie。

使用增強式密碼。規則運算式可用來確保使用者提供的密碼符合適當的複雜性需求。

在資料庫中儲存密碼檢查器。儲存不可還原的密碼雜湊並結合隨機 salt 值,以降低字典攻擊的風險。

關於在資料庫中儲存密碼雜湊和其他機密的詳細資訊,請參閱單元 14<建置安全的資料存取>。

參數操作

參數是指透過網路從用戶端傳送到伺服器的資料項目。它們包括表單欄位、查詢字串、檢視狀態、Cookie 和 HTTP 標頭。如果伺服器上的機密資料或用來形成安全性決策的資料是使用未受保護的參數傳送,則應用程式很可能遭受資訊洩露或未授權存取。

弱點

會導致參數操作的弱點包括:

使用包含機密資料的隱藏式表單欄位或查詢字串

透過未加密連線傳送包含安全機密資料的 Cookie

攻擊

參數操作攻擊包括:

Cookie 重新執行攻擊。攻擊者擷取並改變 Cookie,然後在應用程式中重新執行它。如果 Cookie 包含的資料是用於伺服器的驗證或授權,則這樣很容易導致偽造識別身份和權限升高。

隱藏式表單欄位的操作。這些欄位包含用於伺服器安全決策的資料。

查詢字串參數的操作

因應對策

您可以運用下列因應對策來防止參數操作:

不要依賴用戶端狀態管理選項。避免使用任何用戶端狀態管理選項來儲存機密資料,如檢視狀態、Cookie、查詢字串或隱藏式表單欄位。

將機密資料儲存在伺服器上。使用工作階段權杖將使用者的工作階段與在伺服器上維護的機密資料項目相關聯。

使用訊息驗證程式碼 (MAC) 來保護工作階段權杖。將它搭配伺服器上的驗證、授權和商業邏輯,以確定該權杖不會重新執行。

網路竊聽

網路竊聽涉及使用網路監視軟體追蹤在瀏覽器和 Web 伺服器之間傳送的資料封包。這可能導致應用程式專屬機密資料公開、登入認證遭擷取或驗證 Cookie 遭擷取。

弱點

會導致成功的網路竊聽的弱點包括:

傳送機密資料時缺乏加密

透過未加密通道傳送驗證 Cookie

攻擊

網路竊聽攻擊是利用位於網路上的封包竊聽工具擷取資料傳輸來執行。

因應對策

若要反制網路竊聽,請使用 Secure Sockets Layer (SSL),在瀏覽器和 Web 伺服器之間提供加密的通訊管道。每當透過網路傳送認證、驗證票證或機密應用程式資料時,都必須使用 SSL。

資訊洩露

當攻擊者探查網頁,設法引起例外狀況時,即發生資訊洩露。這為攻擊者帶來很大的收穫,因為例外詳細資料通常會以 HTML 格式顯示在瀏覽器上,洩露了非常有用的資訊,例如包含資料庫連線字串、資料庫名稱、資料庫結構描述資訊、SQL 陳述式和作業系統及平台版本等內容的堆疊追蹤。

弱點

會造成資訊洩露的弱點包括:

安全性不足的例外處理

讓原始例外詳細資料傳入用戶端

攻擊

有許多攻擊會導致資訊洩露。其中包含:

緩衝區溢位。

傳送故意寫錯的輸入。

因應對策

若要防止資訊洩露:

使用結構化例外處理。

傳回一般錯誤網頁給用戶端。

使用包含一般無害錯誤訊息的預設重新導向網頁。

回到頁首回到頁首

設計考量

在開發網頁和控制項之前,有一些重要議題在設計時期就應該先考量。以下是主要考量:

使用伺服器端輸入驗證

分割網站

考量用於資源存取的識別身份

保護認證和驗證票證

安全地失敗

考量授權細微性

在不同組件中放置 Web 控制項和使用者控制項

在不同組件中放置資源存取碼

使用伺服器端輸入驗證

在設計時期,識別網頁和控制項處理的使用者輸入的所有不同來源。這包括從 Web 使用者接收的表單欄位、查詢字串和 Cookie 以及後端資料來源的資料。Web 使用者很明顯地是位於您應用程式的信任範圍之外,因此該來源的所有輸入必須在伺服器加以驗證。除非您絕對信任從後端資料來源擷取到的資料,否則在將它傳送至用戶端之前,也必須先驗證及進行安全性過濾。確定解決方案不依賴用戶端驗證,因為這容易被忽略。

分割網站

網站設計應明確區分公共存取區域和需要驗證存取的受限制區域。在應用程式的虛擬根目錄下使用不同的子目錄來維護受限制網頁,例如典型電子商務網站中的出庫功能,它需要驗證存取及傳輸像信用卡號碼之類的機密資料。不同子目錄可讓您套用更多安全性措施 (例如,要求 SSL),而不會在整個網站上帶來 SSL 效能負荷。它也可以讓您降低連線劫持的風險,因為它限制驗證 Cookie 到 HTTP 連線的傳輸。[圖 10.2] 顯示典型劃分。

劃分成公共區域和安全區域的網站

[圖 10.2]
劃分成公共區域和安全區域的網站

請注意,在 [圖 10.2] 中的 Internet Information Services (IIS) 有設定受限制的子資料夾來要求 SSL 存取權。Web.config 中的第一個 <authorization> 元素可讓所有使用者存取共用區域,第二個元素可防止未驗證過的使用者存取受保護子資料夾的內容及強制執行登入。

關於限制驗證 Cookie 使其只能透過 HTTPS 連線傳送以及關於如何在受限制網頁和非限制網頁之間瀏覽的詳細資訊,請參閱本單元的「驗證」一節中的「使用絕對 URL 進行瀏覽」。

考量用於資源存取的識別身份

在預設的狀況下,ASP.NET 應用程式不模擬,並且使用最小權限的 ASPNET 處理序帳戶來執行 ASP.NET Web 應用程式及資源存取。預設值是建議的設定。在某些情況下,您可能想要使用不同的 Windows 安全性內容來進行資源存取。其中包含:

在相同伺服器上裝載多個應用程式
您可以使用 IIS 設定每一個應用程式使用不同的匿名 Internet 使用者帳戶,然後啟用模擬。於是每一個應用程式就有不同的識別身份來存取資源。有關此方法的詳細資訊,請參閱單元 20<裝載多個 Web 應用程式>。

存取具有特定驗證需求的遠端資源
如果您需要存取特定遠端資源 (例如,檔案共用) 且已有特定 Windows 帳戶可使用,那麼您可以設定此帳戶作為應用程式的匿名 Web 使用者帳戶。然後您可以在存取特定遠端資源之前使用程式設計模擬。如需詳細資訊,請參閱本單元後面的「模擬」。

保護認證和驗證票證

您在設計時應該將如何保護認證和驗證票證列為重要因素。如果認證要透過網路傳遞且位於設定檔之類的永久存放區內,則需要受到保護。認證票證在網路上必須受到保護,因為它們很容易被劫持。加密提供了解決方案。SSL 或 IPSec 可用來保護網路上的認證和票證,DPAPI 則提供理想的解決方案來加密設定檔中的認證。

安全地失敗

如果應用程式失敗時發生無法復原的例外狀況,請確定它的失敗很安全,不會讓系統門戶大開。確定惡意使用者所重視的例外詳細資料不會傳入用戶端,而是傳回一般錯誤網頁。規劃使用結構式例外處理方式來處理錯誤,而不依賴方法錯誤碼。

考量授權細微性

考量您在網站的已驗證部份中使用的授權細微性。如果您已設定目錄需要驗證,那麼所有使用者是否對該目錄的頁面具有同等存取權?必要時,您可以依據識別身份或更常見的呼叫者角色成員,在不同的<location> 元素內使用多個 <authorization> 元素,來對不同頁面套用不同授權規則。

例如,相同目錄中的兩頁可以在 Web.config 中具有不同的 <allow> <deny> 元素。

在不同組件中放置 Web 控制項和使用者控制項

當 Web 控制項及使用者控制項各放在它們自己的組件時,您可以利用程式碼存取安全性原則,為每一個組件單獨設定安全性。這賦予系統管理員更大的彈性,表示不會只為了滿足單一控制項的需求而強迫您授與太多許可權給所有控制項。

在不同組件中放置資源存取碼

使用不同組件並從頁面類別呼叫它們,而不是將資源存取碼內嵌於頁面類別事件控制代碼中。這為程式碼存取安全性原則提供更大的彈性,而且對於建立部分信任的 Web 應用程式特別重要。如需詳細資訊,請參閱單元 9<配合 ASP.NET 使用程式碼存取安全性>。

回到頁首回到頁首

輸入驗證

如果您對輸入的型別、長度、格式或範圍做了沒有事實根據的假設,則應用程式不可能功能健全。如果攻擊者發現您做了沒有事實根據的假設,則輸入驗證會變成安全問題。攻擊者就會提供製作精巧的輸入來侵害應用程式。對使用者輸入的不當信任是 Web 應用程式最常見、破壞力最大的弱點之一。

限制,然後進行安全性過濾

一開始先限制輸入,並藉由驗證型別、長度、格式和範圍來檢查已知的適當資料。有時候您也需要對輸入進行安全性過濾,使潛在的惡意輸入安全。例如,如果應用程式支援任意格式輸入欄位,例如註解欄位,您可以允許某些「安全的」HTML 元素,例如 <b> <i>,並刪去其他 HTML 元素。下表彙總可用於限制資料及進行安全性過濾的選項:

[表 10.1] 用於限制資料及進行安全性過濾的選項

需求選項

型別檢查

.NET Framework 型別系統。剖析字串資料,轉換為增強式型別,然後處理 FormatExceptions。
規則運算式。使用 ASP.NET RegularExpressionValidator 控制項或 Regex 類別。

長度檢查

規則運算式
String.Length 內容

格式檢查

用於符合
.NET Framework 型別系統的模式的規則運算式

範圍檢查

ASP.NET RangeValidator 控制項 (支援貨幣、日期、整數、倍整數和字串資料)
型別資料比較

規則運算式

您可以使用規則運算式限制有效字元的範圍,刪去不要的字元,及執行長度和格式檢查。您可以定義輸入必須符合的模式來限制輸入格式。ASP.NET 提供 RegularExpressionValidator 控制項,Regex 類別可來自 System.Text.RegularExpressions 名稱區。

如果您使用驗證器控制項,當控制項空白時,驗證成功。對於必要欄位,請使用 RequiredFieldValidator。同時,規則運算式驗證實作在用戶端和伺服器上稍有不同。在用戶端是使用 Microsoft JScript® 開發軟體的規則運算式語法。在伺服器則使用 System.Text.RegularExpressions.Regex 語法。由於 JScript 規則運算式語法是 System.Text.RegularExpressions.Regex 語法,因此建議使用 JScript 規則運算式語法在用戶端和伺服器上產生相同結果。

有關 ASP.NET 驗證器控制項的完整範圍的詳細資訊,請參閱 .NET Framework 說明文件。

RegularExpressionValidator 控制項

若要驗證 Web 表單欄位輸入,您可以使用 RegularExpressionValidator 控制項。將此控制項拖曳到 Web 表單,並設定它的 ValidationExpressionControlToValidateErrorMessage 內容。

您可以使用 Microsoft Visual Studio® .NET 中的內容視窗來設定驗證表示式,也可以在 Page_Load 事件控制碼中動態地設定內容。後者可讓您將網頁上所有控制項的所有規則運算式組在一起。

Regex 類別

如果您使用一般 HTML 控制項但不含 runat="server" 內容 (它使用 RegularExpressionValidator 控制項除排),或者您需要驗證其他來源的輸入,如查詢字串或 Cookie,您可以在網頁類別或在驗證協助程式方法中使用 Regex 類別,或許可以用個別組件的方式進行。本節後面將提供一些範例。

規則運算式註解

如果您使用下列語法並使用 # 對表示式的每一個元件加上註解,則規則運算式較容易了解。若要啟用註解,您還必須指定 RegexOptions.IgnorePatternWhitespace,這表示忽略非逸出空白區。

Regex regex = new Regex(@"
^           # anchor at the start
(?=.*\d)     # must contain at least one digit
(?=.*[a-z])  # must contain one lowercase
(?=.*[A-Z])  # must contain one uppercase
.{8,10}      # From 8 to 10 characters in length
$            # anchor at the end", 
RegexOptions.IgnorePatternWhitespace);

字串欄位

若要驗證字串欄位,例如名稱、位址、稅務識別碼等等,請使用規則運算式來執行下列動作:

限制輸入字元的可接受範圍。

套用格式化規則。例如,模式型欄位如稅務識別碼、郵遞區號,需要特定模式的輸入字元。

檢查長度。

名稱

下列範例顯示已用來驗證名稱欄位的 RegularExpressionValidator 控制項。

<form id="WebForm" method="post" runat="server">
<asp:TextBox id="txtName" runat="server"></asp:TextBox>
<asp:RegularExpressionValidator id="nameRegex"runat="server" 
ControlToValidate="txtName" 
ValidationExpression="^[a-zA-Z'.`-?\s]{1,40}$" 
ErrorMessage="Invalid name">
</asp:regularexpressionvalidator>
</form>

前述驗證表示式限制輸入名稱欄位為字母字元 (小寫和大寫),名稱使用單引號 (如 O'Dell) 及 dot (.) 字元。此外,欄位長度限制為 40 個字元。

身分證字號

下列範例顯示對 RegularExpressionValidator 控制項產生的 HTML 程式碼,此控制項是用來驗證美國社會安全碼表單欄位:

<form id="WebForm" method="post" runat="server">
<asp:TextBox id="txtSSN" runat="server"></asp:TextBox>
<asp:RegularExpressionValidator id="ssnRegex" runat="server" 
ErrorMessage="Invalid social security number" 
ValidationExpression="\d{3}-\d{2}-\d{4}" 
ControlToValidate="txtSSN">
</asp:RegularExpressionValidator>
</form>

前述驗證表示式是 Visual Studio .NET 提供的標準表示式之一。它驗證所提供輸入欄位的格式以及它的型別和長度。此輸入必須包含三位數字,其後接著斷字符號,然後兩位數字,其面接著斷字符號,然後四位數字。

如果您不使用伺服器控制項 (它排除驗證器控制項),或您需要驗證表單欄位以外的來源的輸入,您可以在方法程式碼中使用 System.Text.RegularExpression.Regex 類別。下列範例顯示如何直接在網頁類別中使用靜態 Regex.IsMatch 方法而不使用驗證器控制項來驗證相同欄位:

if (!Regex.IsMatch(txtSSN.Text, @"^\d{3}-\d{2}-\d{4}$"))
{
// 無效身份證字號
}

日期欄位

有相等 .NET Framework 型別的輸入欄位可利用 .NET Framework 型別系統檢查其型別。例如,若要驗證日期,您可以將輸入值轉換成 System.DateTime 型別的變數,如果輸入資料不相容,可處理任何產生的格式例外,如下所示。

try
{
DateTime dt = DateTime.Parse(txtDate.Text).Date;
}
// 如果型別轉換失敗,會發生 FormatException
catch( FormatException ex )
{
// 傳回無效日期訊息至呼叫者
}

除了格式和型別檢查之外,您還需要對日期欄位執行範圍檢查。使用 DateTime 變數即可輕易執行此檢查,如下所示。

// 為了簡單起見,省略例外處理
DateTime dt = DateTime.Parse(txtDate.Text).Date;
// 日期必須是今天或更早
if ( dt > DateTime.Now.Date )
throw new ArgumentException("Date must be in the past");

數字欄位

如果您需要驗證數字資料,例如年齡,請使用 int 型別執行型別檢查。若要將字串輸入轉換成整數形式,您可以使用使用 Int32.Parse Convert.ToIn32,然後處理因無效資料型別而發生的任何 FormatException ,如下所示:

try
{
int i = Int32.Parse(txtAge.Text);
  . . .
}
catch( FormatException)
{
 . . .
}

範圍檢查

有時候您需要驗證輸入資料是否在預定範圍內。下列程式碼使用 ASP.NET RangeValidator 控制項來限制輸入為 0 和 255 之間的整數。此範例亦使用 RequiredFieldValidator。若無 RequiredFieldValidator,另一個驗證器控制項接受空白輸入。

<form id="WebForm3" method="post" runat="server">
<asp:TextBox id="txtNumber" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator 
id="rangeRegex" 
runat="server" 
ErrorMessage="Please enter a number between 0 and 255" 
ControlToValidate="txtNumber"
style="LEFT: 10px; POSITION: absolute; TOP: 47px" >
</asp:RequiredFieldValidator>
<asp:RangeValidator 
id="RangeValidator1" 
runat="server" 
ErrorMessage="Please enter a number between 0 and 255" 
ControlToValidate="TextBox1" 
Type="Integer" 
MinimumValue="0"
MaximumValue="255" 
style="LEFT: 10px; POSITION: absolute; TOP: 47px" >
</asp:RangeValidator>
<asp:Button id="Button1" style="LEFT: 10px; POSITION: absolute; TOP: 100px" 
runat="server" Text="Button"></asp:Button>
</form>

下列範例顯示如何使用 Regex 類別驗證範圍:

try
{
// 若轉換無效會發生例外。
int i = Convert.ToInt32(sInput);
if ((0 <= i && i <= 255) == true)
  {
// 資料有效,使用數字
  }
}
catch( FormatException )
{
  . . .
}

對輸入進行安全性過濾

安全性過濾可使潛在惡意資料變安全。當允許的輸入範圍無法保證輸入安全時,這樣做很有幫助。這包括從使用者提供的字串中刪去空字元 (Null),或逸出值而視同文字加以處理。如果您需要對輸入進行安全性過濾,並轉換或刪去特定輸入字元,請使用 Regex.Replace

注意 全面防禦請使用此方式。開始時一律將輸入限制為一組已知的「適當」值。

下列程式碼刪去可能不安全的一個字元範圍,包括 <>\"'%;()&。

private string SanitizeInput(string input)
{
Regex badCharReplace = new Regex(@"^([<>""'%;()&])$");
string goodChars = badCharReplace.Replace(input, "");
return goodChars;
}

有關對任意格式輸入欄位 (例如註解欄位) 進行安全性過濾的詳細資訊,請參閱本單元後面「跨網站指令碼」之下的「對任意格式輸入進行安全性過濾」。

驗證 HTML 控制項

如果您不使用伺服器控制項 — 亦即具有 runat="server" 屬性的控制項 — 而使用一般 HTML 控制項,則您無法使用 ASP.NET 驗證器控制項。但您可以在 Page_Load 事件控制碼中使用規則運算式來驗證網頁內容,如下所示。

using System.Text.RegularExpressions;
. . .
private void Page_Load(object sender, System.EventArgs e)
{
// 請注意,IsPostBack 僅適用於
// 伺服器表單 (with runat="server")
if ( Request.RequestType == "POST" ) // 非伺服器表單
  {
// 驗證提供的電子郵件位址
if( !Regex.Match(Request.Form["email"], 
@"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$",
RegexOptions.None).Success) 
    {
// 無效電子郵件位址
    }
// 驗證提供的名稱
if ( !RegEx.Match(Request.Form["name"],
@"^[A-Za-z'\- ]$",
RegexOptions.None).Success) 
    {
// 無效名稱
    }
  }
}

驗證用於資料存取的輸入

如果您要建立的動態 SQL 查詢是基於使用者輸入,則 SQL 注入攻擊會注入惡意的 SQL 命令,而資料庫可能會加以執行。在典型的網頁型資料存取狀況中,可使用下列全面防禦策略:

使用規則運算式限制輸入在網頁類別內。

進行安全性過濾或拒絕輸入。若要全面防禦,您可以選擇使用協助程式方法來刪去空字元或其他已知的錯誤字元。

對資料存取使用參數化預存程序,以確定對 SQL 查詢中使用的資料執行型別和長度檢查。

有關對資料存取使用參數以及有關撰寫安全資料存取碼的詳細資訊,請參閱單元 14<建置安全的資料存取>。

驗證用於檔案 I/O 的輸入

一般而言,您應該避免撰寫接受呼叫者的檔案輸入或路徑輸入的程式碼。相反地,在讀取和寫入資料時請使用固定檔名和位置。這可確保程式碼不會被迫存取任意檔案。它也確保程式碼不易發生標準化 (canonicalization) 錯誤。

如果您一定要接受輸入檔名,則會面臨兩大挑戰。首先,產生的檔案路徑和名稱是有效的檔案系統名稱嗎?其次,此路徑在應用程式內容中有效嗎?例如,它是否位於應用程式的虛擬目錄 root 之下?

若要標準化檔名,請使用 System.IO.Path.GetFullPath。若要檢查檔案路徑在應用程式內容中是否有效,您可以使用 .NET 程式碼存取安全性來授與精確的 FileIOPermission 給程式碼,使它只能存取特定目錄中的檔案。如需詳細資訊,請參閱單元 7<建置安全的組件>和單元 8<程式碼存取安全性實務>中的「檔案 I/O」章節。

使用 MapPath

如果您使用 MapPath 將所提供的虛擬路徑對應到伺服器上的實體路徑,請使用 Request.MapPath 的超載來接受 bool 參數,讓您能防止跨應用程式對應,如下所示:

try
{
string mappedPath = Request.MapPath( inputPath.Text, 
Request.ApplicationPath, false);
}
catch (HttpException)
{
// 嘗試跨應用程式對應
}	

最終 false 參數防止跨應用程式對應。這表示使用者無法順利提供包含 ".." 的路徑來越過應用程式虛擬目錄階層之外。若嘗試這麼做,會導致 HttpException 型別的例外發生。

注意 伺服器控制項可使用 Control.MapPathSecure 方法來讀取檔案。此方法需要呼叫程式碼獲得程式碼存取安全性原則的完全信任;否則會發生 HttpException 。如需詳細資訊,請參閱 .NET Framework SDK 說明文件中的 Control.MapPathSecure

常見的規則運算式

Visual Studio .NET 提供一組有用的規則運算式。若要存取它們,請在 Web 表單上加入 RegularExpresssionValidator 控制項,並按一下該控制項的 Expression 內容欄位中的省略符號按鈕。下表顯示常用的網頁欄位的其他幾個有用的表示式。

[表 10.2] 有用的規則運算式欄位

欄位 表示式格式範例說明

名稱

[a-zA-Z'`-?\s]{1,40}

John DoeO'Dell

驗證名稱。允許最多 40 個大寫和小寫字元,以及部份名稱常見的幾個特殊字元。可修改此清單。

數字

^\D?(\d{3})\D?\D?(\d{3})\D?(\d{4})$

(425)-555-0123
425-555-0123
425 555 0123

驗證美國電話號碼。

電子郵件

\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*

someone@example.com

驗證電子郵件位址。

URL

^(http|https|ftp)\://[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(:[a-zA-Z0-9]*)?/?([a-zA-Z0-9\-\._\?\,\'/\\\+&%\$#\=~])*$

 

驗證 URL。

郵遞區號

^(\d{5}-\d{4}|\d{5}|\d{9})$|^([a-zA-Z]\d[a-zA-Z] \d[a-zA-Z]\d)$

 

驗證美國郵遞區號,允許 5 或 9 位數字。

密碼

^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$

 

驗證增強式密碼。必須介於 8 和 10 個字元之間。必須包含大寫、小寫和數字的組合,且無特殊字元。

非負整數

\d+

0986

驗證大於零的整數。

貨幣 (非負數)

"\d+(\.\d\d)?"

 

驗證正數貨幣金額。小數點後面需要兩位數。

貨幣 (正數或負數)

"(-)?\d+(\.\d\d)?"

 

驗證正數或負數貨幣金額。小數點後面需要兩位數。

回到頁首回到頁首

跨網站指令碼

XSS 攻擊利用網頁驗證的弱點,注入用戶端指令碼。此程式碼後來傳回給使用者並由瀏覽器執行。因為瀏覽器是從信任的網站下載指令碼,所以瀏覽器無法識別該程式碼是否合法,Internet Explorer 安全性區域不提供防禦功能。XSS 攻擊也可透過 HTTP 或 HTTPS (SSL) 連線運作。其中一項最嚴重的利用,是發生於攻擊者撰寫程式碼來擷取驗證 Cookie,而此 Cookie 提供對信任網站的存取權並將它張貼到攻擊者已知的一個網址。這使攻擊者得以冒充合法使用者的識別身份,而取得網站的非法存取權。

請使用下列因應對策來防止 XSS 攻擊:

驗證輸入

編碼輸出

驗證輸入

使用本單元前述各項技術,驗證從應用程式信任界限外接收的型別、長度、格式和範圍的輸入。

編碼輸出

如果您撰寫文字輸出至網頁,但您不十分確定該文字是否未包含 HTML 特殊字元 (例如 <>&),那麼,請務必使用 HttpUtility.HtmlEncode 方法進行前置處理。即使文字是來自使用者輸入、資料庫或本機檔案,也要這麼做。同樣地,請使用 HttpUtility.UrlEncode 來編碼 URL 字串。

HtmlEncode 方法將 HTML 中具有特殊意義的字元取代成代表那些字元的 HTML 變數。例如,< 取代成 < " 取代成 "。編碼資料不會導致瀏覽器執行程式碼。相反地,該資料會以無害的 HTML 呈現。

Response.Write(HttpUtility.HtmlEncode(Request.Form["name"]));

資料繫結控制項

資料繫結 Web 控制項不編碼輸出。唯一編碼輸出的控制項是 TextBox 控制項,其 TextMode 內容是設定為 MultiLine。如果您連結任何其他控制項至含有惡意 XSS 程式碼的資料,則會在用戶端上執行該程式碼。因此,如果您從資料庫擷取資料時並不確定資料是否有效 (或許因為它是與其他應用程式共用的資料庫),請在傳回給用戶端之前先編碼資料。

對任意格式輸入進行安全性過濾

如果網頁包括任意格式的文字框 (如「註解」欄位),但您希望它允許某些安全的 HTML 元素,例如 <b> <i>,那麼您可以先使用 HtmlEncode 進行前置處理,然後選擇性地移除允許元素上的編碼,這樣就可以安全地處理了,如下所示:

StringBuilder sb = new StringBuilder( HttpUtility.HtmlEncode(userInput) ) ;
sb.Replace("<b>", "<b>");
sb.Replace("</b>", "</b>");
sb.Replace("<i>", "<i>");
sb.Replace("</i>", "</I>");
Response.Write(sb.ToString());

全面防禦因應對策

除了前述技術之外,請使用下列因應對策全面防禦 XSS:

設定正確字元編碼

使用 ASP.NET 第 1.1 版 validateRequest 選項

在 Web 伺服器安裝 URLScan

使用 HttpOnly Cookie 選項

使用 <frame> 安全性屬性

使用 innerText 內容

設定正確字元編碼

若要成功地限制網頁的有效資料,一定要限制輸入資料的代表方式。這樣可防止惡意使用者利用標準化和多位元組逸出序列來欺騙輸入驗證常式。

ASP.NET 可讓您藉由在 Web.config 中使用 <globalization> 元素,在網頁層級或應用程式層級指定字元集。以下使用舊版 HTML 和 HTTP 預設的 ISO-8859-1 字元編碼來顯示這兩種方式。

若要在網頁層級設定字元編碼,請使用 <meta> 元素或 ResponseEncoding 網頁層級屬性,如下所示:

<meta http-equiv="Content Type" 
content="text/html; charset=ISO-8859-1" />

<% @ Page ResponseEncoding="ISO-8859-1" %>

若要在 Web.config 中設定字元編碼,請使用下列設定:

<configuration>
<system.web>
<globalization 
requestEncoding="ISO-8859-1"
responseEncoding="ISO-8859-1"/>
</system.web>
</configuration>

驗證 Unicode 字元

使用下列程式碼來驗證網頁中的 Unicode 字元:

using System.Text.RegularExpressions;
. . .
private void Page_Load(object sender, System.EventArgs e)
{
// 名稱必須包含 1 到 40 個英數字元,
// 以及 (選擇性地) 特殊字元 '`?,例如像
// D'Angelo 這樣的名稱
if (!Regex.IsMatch(Request.Form["name"], @"^[\p{L}\p{Zs}\p{Lu}\p{Ll}]{1,40}$"))
throw new ArgumentException("Invalid name parameter");
// 使用個別規則運算式來驗證其他參數
  . . .
}

以下說明上述程式碼所顯示的規則運算式:

{<name>} 指定已命名的 Unicode 字元類別。

\p{<name>} 對應 {<name>} 所指定的已命名字元類別中的任何字元。

{L} 執行從左到右對應。

{Lu} 執行大寫對應。

{Ll} 執行小寫對應。

{Zs} 對應分隔字元和空格。

{1,40} 表示不小於 1 個但不大於 40 個字元。

{Mn} 對應標記和非空格字元。

{Zs} 對應分隔字元和空格。

* 指定有零個或多個相符。

$ 表示不查看此位置。

使用 ASP.NET validateRequest 選項

validateRequest 屬性是 .NET Framework 1.1 版的功能。在預設的狀況下,此屬性在 Machine.config 的 <pages> 元素上是設定為 true。它指示 ASP.NET 檢查所有從瀏覽器接收到的資料是否為潛在的惡意輸入,例如包含 <script> 元素的輸入。ASP.NET 檢查從 HTML 表單欄位、Cookie 和查詢字串中接收的輸入。.NET Framework 1.0 版不提供任何相等功能,但 IIS URLScan Internet Server Application Programming Interface (ISAPI) 篩選器可執行類似工作。您也可以使用 @ Page 標籤在每一頁套用此設定,如下所示:

<% @ Page validateRequest="True" %>

在 Web 伺服器安裝 URLScan

URLScan 是您執行 IISLockdown 工具時安裝的 ISAPI 篩選器。這可拒絕潛在的惡意輸入,有助於減輕 XSS 攻擊的威脅。如需 IISLockdown 和 URLScan 的詳細資訊,請參閱單元 16<保障 Web 伺服器的安全>。

注意 Windows Server 2003 上的 IIS 6.0 有 URLScan 內建程式的相等功能。

使用 HttpOnly Cookie 選項

Internet Explorer 6 Service Pack 1 支援新的 HttpOnly Cookie 屬性,它可防止用戶端指令碼存取 document.cookie 內容中的 Cookie。反之,會傳回空的字串。每當使用者瀏覽至目前網域中的網站時,這個 Cookie 仍會傳送至伺服器。

注意 不支援 HttpOnly Cookie 屬性的 Web 瀏覽器可能會忽略該 Cookie 或忽略該屬性,這表示仍可能遭受 XSS 攻擊。

System.Net.Cookie 類別目前不支援 HttpOnly 內容。若要在 Cookie 中加入 HttpOnly 屬性,您必須使用 ISAPI 篩選器,如果您想要一個 Managed 程式碼解決方案,請將下列程式碼加入應用程式的 Global.asax 的 Application_EndRequest 事件控制碼中:

protected void Application_EndRequest(Object sender, EventArgs e) 
{
string authCookie = FormsAuthentication.FormsCookieName;
foreach (string sCookie in Response.Cookies) 
  {
// 只在表單驗證 Cookie 上設定 HttpOnly 屬性
// 略過此檢查,在集合的所有 Cookie 上設定此屬性
if (sCookie.Equals(authCookie))
    { 
// 強迫 HttpOnly 加入 Cookie 標頭中
Response.Cookies[sCookie].Path += ";HttpOnly";
    }
  }
}

注意 .NET Framework 的新版本可能會在 Cookie 類別上加入 HttpOnly 內容。

使用 <frame> 安全性屬性

Internet Explorer 6 與更新的版本在 <frame> <iframe> 元素上,能支援新的 security 屬性。您可以使用 security 屬性,對個別的 frame iframe 套用使用者的受限制網站 Internet Explorer 安全性區域設定。在預設的狀況下,受限制網站區域不支援指令碼執行。如果您使用 security 屬性,它目前必須設定為 "restricted",如下所示:

<frame security="restricted" src="http://www.somesite.com/somepage.htm"></frame>

使用 innerText 屬性

如果您建立的網頁含有不受信任的輸入,請使用 innerText 屬性,而不要使用 innerHTMLinnerText 屬性可以安全地呈現內容,並確保指令碼不會執行。

回到頁首回到頁首

驗證

安全性不足的驗證增加偽造識別身份的威脅。如果使用者的登入認證落入壞人之手,攻擊者可能會冒充該使用者的識別身份,而取得應用程式的存取權。攻擊者將共用該使用者在應用程式中的所有權限。認證必須受到保護,因為它們透過網路傳遞,且永久存放於應用程式的使用者存放區內。驗證 Cookie 代表初次登入之後在應用程式中的一個已驗證識別身份,它也必須受到保護,以降低連線劫持和 Cookie 重新執行的風險。

表單驗證

連線劫持和 Cookie 重新執行的攻擊,此類威脅對於使用表單驗證的應用程式特別重要。在使用使用者提供的認證來查詢資料庫時,您必須特別小心,以確定不會發生 SQL 注入。另外,若要防止偽造識別身份,您應該確定使用者存放區的安全,並使用增強式密碼。

下列片段顯示 Web.config 中的「安全」表單驗證設定:

<forms loginUrl="Restricted\login.aspx"  Login page in an SSL protected folder
protection="All"                  Privacy and integrity
requireSSL="true"                 Prevents cookie being sent over http
timeout="10"                      Limited session lifetime
name="AppNameCookie"              Unique per-application name
path="/FormsAuth"                    and path
slidingExpiration="true" >        Sliding session lifetime
</forms>

下列建議有助於您建立安全的表單驗證解決方案:

分割網站

利用 SSL 保障受限制網頁的安全

使用 URL 授權

保障驗證 Cookie 的安全

使用絕對 URL 進行瀏覽

使用安全認證管理

分割網站

在設計網站時,需要驗證存取的安全網頁務必放在與匿名存取網頁不同的子目錄中。[圖 10.3] 顯示 Visual Studio .NET Solution Explorer 視窗的典型設置。請注意表單登入網頁與其他受限制網頁是如何放在不同的子目錄中。

需要驗證存取的受限制網頁的子目錄

[圖 10.3]
需要驗證存取的受限制網頁的子目錄

注意 如果您在應用程式中使用 Server.Transfer ,從匿名網頁傳送到安全網頁,.NET Framework 第 1.1 版或更舊的版本會略過驗證檢查,因此,應該驗證使用 Server.Transfer 的程式碼,以確定它未傳送至安全目錄。

利用 SSL 保障受限制網頁的安全

若要確定 SSL 用來保護登入表單所張貼以及已驗證的 Cookie 在後續要求中傳送至受限制網頁的登入認證,請在 IIS 中設定安全資料夾來要求 SSL。這樣會在 IIS metabase 中設定資料夾的 AccessSSL=true 屬性。唯有當 https 使用於要求 URL 時,對受保護資料夾中的網頁的要求才會成功。

對於 SSL,您必須在 Web 伺服器上安裝伺服器憑證。如需詳細資訊,請參閱《Microsoft patterns & practices Volume I, 建置安全的 ASP.NET 應用程式: 驗證、授權和安全通訊》中的<How To>一節中的<How To: Setup SSL on a Web Server>,網址是:http://www.microsoft.com//taiwan/msdn/books/ataglance/secnetlpMSDN.htm

使用 URL 授權

若要允許匿名存取公用網頁,請使用下列 <authorization> 元素。

<system.web>
<!-- 虛擬目錄根資料夾內包含一般頁面。
未經驗證的使用者可以檢視這些頁面,而且這些頁面不需要
利用 SSL 加以保護。 -->
<authorization>
<allow users="*" />
</authorization>
</system.web>

使用 Web.config 中的 <location> 元素內的下列 <authorization> 元素,拒絕未授權使用者的存取,並強制重新導向 <forms> 元素所指定的登入網頁。

<!-- 受限制的資料夾僅用於驗證過的和 SSL 的存取。 -->
<location path="Secure" >
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
</location>

保障驗證 Cookie 的安全

若要防止連線劫持和 Cookie 重新執行的攻擊,請確定 Cookie 僅使用 HTTPS 通訊協定並透過 SSL 連線傳送,來保障 Cookie 的安全。若要進一步降低風險,請在傳送至用戶端之前加密 Cookie,並限制 Cookie 的有效期。若要保障驗證 Cookie 的安全:

限制驗證 Cookie 僅使用 HTTPS 連線

加密 Cookie

限制 Cookie 存留期

考慮使用固定到期日

不要保持永久的驗證 Cookie

分開存放驗證 Cookie 和個人化 Cookie

使用特殊 Cookie 名稱和路徑

限制驗證 Cookie 到 HTTPS 連線

Cookie 支援「安全」內容,可決定瀏覽器是否應該將 Cookie 傳回至伺服器。有了安全內容設定,瀏覽器只會將 Cookie 傳送至使用 HTTPS URL 要求的安全網頁。

如果您使用 .NET Framework 1.1 版,請在 <forms> 元素上使用 requireSSL="true" 來設定安全內容,如下所示:

<forms loginUrl="Secure\Login.aspx"
requireSSL="true" . . . />

如果您使用 .NET Framework 1.0 版,請使用下列程式碼,在 Global.asax 的 Application_EndRequest 事件控制碼中設定安全內容:

protected void Application_EndRequest(Object sender, EventArgs e) 
{
string authCookie = FormsAuthentication.FormsCookieName;

foreach (string sCookie in Response.Cookies) 
  {
if (sCookie.Equals(authCookie))
    { 
// 設定安全 Cookie。瀏覽器只將 Cookie
// 傳送至以 https 要求的網頁
Response.Cookies[sCookie].Secure = true;
    }
  }
}

加密 Cookie

即使您使用 SSL,也請加密 Cookie 的內容。這樣可防止攻擊者在設法透過 XSS 竊取 Cookie 時檢視或修改 Cookie。在此情況下,攻擊者仍可使用 Cookie 取得您應用程式的存取權。降低此風險的最好方式是實作適當的因應對策來防止 XSS 攻擊 (如本單元前面的「跨網站指令碼」所述),並限制 Cookie 存留期,如下面建議所述。

若要提供 Cookie 隱私性和完整性,請在 <forms> 元素上設定 protection 屬性,如下所示:

<forms protection="All"    Privacy and integrity

限制 Cookie 存留期

限制 Cookie 存留期以減少攻擊者利用所擷取之 Cookie 冒充存取應用程式的時間間隔。

<forms timeout="10"                Reduced cookie lifetime (10 minutes)

考慮使用固定到期日

考慮在 <forms> 元素上設定 slidingExpiration="false" ,以固定 Cookie 的到期日,而不必在每次 Web 要求之後,重新設定到期日。如果您不使用 SSL 來保護 Cookie,則這一點非常重要。

注意 此項功能在 .NET Framework 1.1 版中可以使用。

不要保持永久的驗證 Cookie

不要保持永久的驗證 Cookie,因為它們儲存在使用者的設定檔中,萬一攻擊者能夠實際存取使用者電腦,那它們可能會遭竊。您可以在建立 FormsAuthenticationTicket 時指定非持續性 Cookie,如下所示:

FormsAuthenticationTicket ticket = 
new FormsAuthenticationTicket(
1,                           // 版本
Context.User.Identity.Name,  // 使用者名稱
DateTime.Now,                // 發行時間
DateTime.Now.AddMinutes(15), // 每 15 分鐘到期
false,                       // 不要保持永久性 Cookie
roleStr );                   // 使用者角色

分開存放驗證 Cookie 和個人化 Cookie

請將包含使用者特定偏好設定和非機密資料的個人化 Cookie 與驗證 Cookie 分開存放。個人化 Cookie 遭竊並不構成安全性威脅,但攻擊者卻可以利用失竊的驗證 Cookie 來取得您應用程式的存取權。

使用特殊 Cookie 名稱和路徑

<forms> 元素上使用唯一的 name path 屬性值。確定使用唯一名稱,可在相同伺服器裝載多個應用程式時防止發生潛在問題。例如,如果您不使用特殊名稱,則在一個應用程式驗證過的使用者向另一個應用程式提出要求時,可能不會重新導向該應用程式的登入網頁。

如需詳細資訊,請參閱 Microsoft Knowledge Base 文章 313116《PRB: Forms Authentication Requests Are Not Directed to loginUrl Page (英文)》和 310415《PRB: Mobile Forms Authentication and Different Web Applications (英文)》

使用絕對 URL 進行瀏覽

在網站公用區域和受限制區域之間瀏覽 (亦即,在 HTTP 和 HTTPS 網頁之間) 會有問題,因為重新導向一律使用本網頁而非目標網頁的通訊協定 (HTTPS 或 HTTP)。

一旦使用者登入及瀏覽以 SSL 保護的目錄中的網頁,則相關連結 (如 "..\publicpage.aspx") 或重新導向 HTTP 網頁會造成使用 https 通訊協定提供網頁,而帶來不必要的效能負荷。若要避免發生此情況,從 HTTPS 網頁重新導向 HTTP 網頁時,請使用絕對連結,如 "http://servername/appname/publicpage.aspx"。

同樣地,當您從本身網站的公用區域重新導向安全網頁 (例如,登入網頁) 時,必須使用絕對 HTTPS 路徑 (如 "https://servername/appname/secure/login.aspx") 而不要使用相對路徑 (如 restricted/login.aspx)。例如,如果您網頁有提供登入按鈕,請使用下列程式碼重新導向安全登入網頁。

private void btnLogon_Click( object sender, System.EventArgs e )
{
// 使用伺服器名稱和 v-dir 名稱來建立一個絕對路徑
string serverName = 
HttpUtility.UrlEncode(Request.ServerVariables["SERVER_NAME"]);
string vdirName = Request.ApplicationPath;
Response.Redirect("https://" + serverName + vdirName + 
"/Restricted/Login.aspx");
}

使用安全認證管理

偽造識別身份是應用程式最常見的驗證相關威脅之一。當攻擊者冒充另一位使用者而取得應用程式的存取權時,即發生偽造識別身份。其作法之一是劫持工作階段 Cookie,但如果您有按照前述方式保護驗證 Cookie,則可大幅降低風險。此外,您必須建立安全認證管理和安全使用者存放區,來降低暴力式密碼攻擊、字典攻擊和 SQL 注入攻擊所帶來的風險。

下列建議有助於您降低風險:

對密碼使用單向雜湊

使用增強式密碼

防止 SQL 注入

對密碼使用單向雜湊

如果使用者存放區是 SQL Server,請儲存單向密碼摘要 (雜湊值) 並新增一個隨機 salt 值。新增的 salt 值可降低暴力密碼破解嘗試 (例如字典攻擊) 的風險。摘要方式表示您絕不實際儲存密碼。相反地,您是從使用者擷取密碼,然後重新計算摘要並將它與儲存值做比較,來驗證密碼。

使用增強式密碼

使用規則運算式,以確定使用者密碼符合增強式密碼原則。下列規則運算式可用來確定密碼是介於 8 到 10 個字元的長度,並且混合大寫、小寫、數字和特殊字元。這樣可進一步降低字典攻擊的風險。

private bool IsStrongPassword( string password )
{
}

防止 SQL 注入

表單驗證特別容易產生造成 SQL 注入攻擊的弱點,這是因為使用者提供的登入認證用於查詢資料庫的方式。若要降低此風險:

徹底驗證提供的認證。使用規則運算式以確定它們不包括 SQL 字元。

使用參數化預存程序來存取使用者存放區資料庫。

對資料庫使用受限制及最小權限的登入。

如需防止 SQL 注入的詳細資訊,請參閱單元 14<建置安全的資料存取>。

回到頁首回到頁首

授權

您可以使用授權來控制對目錄、個別網頁、網頁類別和方法的存取。必要時,您也可以在方法程式碼中包括授權邏輯。當您在網頁和控制項中建立授權時,請考慮下列建議:

對網頁和目錄存取控制使用 URL 授權

對 Windows 驗證使用檔案授權

對類別和方法使用主體要求

對細微授權使用明確角色檢查

對網頁和目錄存取控制使用 URL 授權

對網頁層級和目錄層級的存取控制,請使用 URL 授權,它是由 <authorization> 元素設定。若要限制存取特定檔案或目錄,請將 <authorization> 元素放在 <location> 元素內。

如需詳細資訊,請參閱單元 19<保障 ASP.NET 應用程式及 Web 服務的安全>中的「授權」。

對 Windows 驗證使用檔案授權

如果已對 Windows 驗證設定 ASP.NET,FileAuthorizationModule 會檢查要求的 ASP.NET 檔案類型。這包括 ASP.NET 分頁檔 (.aspx)、使用者控制項 (.ascx) 及 IIS 對應到 ASP.NET ISAPI 篩選器的其他檔案類型。

若要設定 FileAuthorizationModule,請在 ASP.NET 檔上設定適當的 Windows 存取控制清單 (ACL)。

對類別和方法使用主體要求

主體權限要求可讓您根據呼叫者的識別身份和角色成員資格做出授權決策。呼叫者的識別身份和角色成員資格是由主體物件維護,它與目前的 Web 要求相關聯 (透過 HttpContext.User 存取)。使用宣告式安全性屬性來提供對類別和方法的存取控制,如下所示:

// 宣告式語法
[PrincipalPermission(SecurityAction.Demand, 
Role=@"DomainName\WindowsGroup")]
public void SomeRestrictedMethod()
{
}

對細微授權使用明確角色檢查

宣告式安全性檢查防止使用者存取類別或呼叫特定方法。如果您需要方法內增加其他邏輯來做出授權決策,請使用命令式主體權限要求,或使用 IPrincipal.IsInRole 的明確角色檢查。這些方式可讓您使用其他 runtime 變數來細部調整授權決策。下列範例顯示命令式主體權限要求的使用:

// 命令式語法
public void SomeRestrictedMethod()
{
// 僅身為指定 Windows 群組成員的呼叫者
// 才能夠存取
PrincipalPermission permCheck = new PrincipalPermission(
null, @"DomainName\WindowsGroup");
permCheck.Demand();
// 某些受限制作業 (省略)
}

下列範例顯示 IPrincipal.IsInRole 的使用:

public void TransferMoney( string fromAccount,
string toAccount, double amount)
{
// 從目前的 HTTP 內容擷取驗證的使用者。
// User 變數相當於 HttpContext.Current.User (如果您
// 使用 .aspx 網頁 (或 .asmx) 的話)
WindowsPrincipal authenticatedUser = User as WindowsPrincipal;
if (null != authenticatedUser)
  {
// 注意:  若要擷取驗證的使用者的使用者名稱,請使用
// 下面這一行程式碼
// string username = authenticatedUser.Identity.Name;
// 如果金額超過臨界值,則需要經理核准
if (amount > thresholdValue) {
// 執行角色檢查
if (authenticatedUser.IsInRole(@"DomainName\Manager") )
      {
// 可以進行轉帳
      }
else
      {
throw new Exception("Unauthorized funds transfer");
      }
    }
else
    {
      . . .
    }
  }
}

您也有方法接受來自數個不同角色的呼叫者。不過,您後來若想呼叫不同方法,這在宣告式安全性是行不通的。

回到頁首回到頁首

模擬

在預設的狀況下,ASP.NET 應用程式通常不會基於設計、實作和擴充性理由而模擬原始呼叫者。例如,模擬會防止有效的中間層連線集區,而對應用程式擴充性造成重大影響。

在某些狀況下,您可能需要模擬 (例如,您需要替代的識別身份 (未處理的識別身份) 來進行資源存取。在主機環境中,通常使用多個匿名的識別身份作為一種應用程式隔離方式。例如,如果應用程式使用表單或 Passport 驗證,您可以模擬匿名的 Internet 使用者帳戶,IIS 將它與應用程式的虛擬目錄相關聯。

您可以模擬原始呼叫者,它可能是匿名的 Internet 使用者帳戶或固定的識別身份。若要模擬原始呼叫者 (IIS 驗證的識別身份),請使用下列設定:

<identity impersonate="true" />

若要模擬固定的識別身份,請在 <identity> 元素上使用另一個 userName password 屬性,並確定您使用 Aspnet_setreg.exe 將加密認證儲存至系統登錄中。有關在設定檔加密認證及關於 Aspnet_setreg.exe 的詳細資訊,請參閱單元 19<保障 ASP.NET 應用程式及 Web 服務的安全>。

使用程式設計模擬

如果您不想針對整個要求模擬帳戶,可使用程式設計模擬,針對要求的一部份來模擬。例如,您想要使用 ASP.NET 處理序帳戶來存取應用程式的主要資源及下游資料庫,但您需要使用替代的識別身份來存取替代資源,例如另一個遠端資料庫或遠端檔案共用。

若要這麼做,請使用 IIS 設定匿名使用者帳戶作為信任的替代識別身份。然後使用下列程式碼建立模擬權杖,唯有當您在執行遠端資源存取碼時才使用匿名帳戶:

HttpContext context = HttpContext.Current;
// 從內容中取得服務提供者
IServiceProvider iServiceProvider = context as IServiceProvider;
//取得代表 HttpContext 的型別 (Type)
Type httpWorkerRequestType = typeof(HttpWorkerRequest);
// 從服務提供者取得 HttpWorkerRequest 服務
// 注意:  若要從 HttpContext 取得 HttpWorkerRequest 型別,
// 需要 Unmanaged 程式碼權限。
HttpWorkerRequest httpWorkerRequest = 
iServiceProvider.GetService(httpWorkerRequestType) as HttpWorkerRequest;
// 取得 IIS 傳送的權杖
IntPtr ptrUserToken = httpWorkerRequest.GetUserToken();
// 從該權杖建立 WindowsIdentity
WindowsIdentity winIdentity = new WindowsIdentity(ptrUserToken);
// 模擬使用者
Response.Write("Before impersonation: " + 
WindowsIdentity.GetCurrent().Name + "<br>");
WindowsImpersonationContext impContext = winIdentity.Impersonate();
Response.Write("Impersonating: " + WindowsIdentity.GetCurrent().Name + "<br>);
// 在此處放置資源存取碼

// 停止模擬
impContext.Undo();
Response.Write( "After Impersonating: " + 
WindowsIdentity.GetCurrent().Name + "<br>");

注意 此方式採用表單或 Passport 驗證,其中應用程式的虛擬目錄是設定在 IIS 中以支援匿名存取。

如果您使用此程式碼,請使用下列 <identity> 設定:

<identity impersonate="false" />

注意 此程式碼採用 Unmanaged 程式碼權限 SecurityPermission(SecurityPermissionFlag.UnmanagedCode),它僅授與完全信任的 Web 應用程式。

回到頁首回到頁首

機密資料

機密資料包括應用程式設定詳細資料 (例如,連線字串和服務帳戶認證) 及應用程式特定資料 (例如,客戶信用卡號碼)。下列建議有助於您在處理機密資料時降低風險:

不要在網頁之間傳送機密資料

避免在設定檔使用純文字密碼

使用 DPAPI 以避免金鑰管理

關閉機密資料的輸出快取

不要在網頁之間傳送機密資料

避免使用任何用戶端狀態管理選項來儲存機密資料,如檢視狀態、Cookie、查詢字串或隱藏式表單欄位變數。此資料可能遭到竄改和以純文字方式檢視。使用伺服器端狀態管理選項來進行安全資料交換,如 SQL Server 資料庫。

避免在設定檔使用純文字密碼

Machine.config 和 Web.config 中的 <processModel><sessionState><identity> 元素具有 userName password 屬性。請勿以純文字儲存它們。請使用 Aspnet_setreg.exe 工具,將加密認證儲存在系統登錄中。

有關在設定檔加密認證及關於 Aspnet_setreg.exe 的詳細資訊,請參閱單元 19<保障 ASP.NET 應用程式及 Web 服務的安全>。

使用 DPAPI 以避免金鑰管理

DPAPI 非常適合加密密碼,例如連線字串和服務帳戶認證。如果網頁需要使用此種設定資料,請使用 DPAPI 來避免金鑰管理問題。

如需詳細資訊,請參閱單元 7<建置安全的組件>中的「密碼編譯」。

關閉機密資料的輸出快取

如果網頁包含機密資料,例如密碼、信用卡號碼或帳戶狀態,則不應快取網頁。若要關閉特定網頁的快取,請使用下列網頁層級屬性:

<%@ Page OutputCache Duration="0" Location="None" VaryByParam="None" %>
回到頁首回到頁首

工作階段管理

若要提供安全工作階段管理,有兩大因素應該列入考量。首先,確定工作階段權杖無法用來取得執行安全作業的機密資料的存取權,或取得資料的機密項目的存取權。其次,如果工作階段包含機密項目,您必須保障工作階段資料的安全,包括工作階段存放區在內。

下列兩種權杖與工作階段管理相關聯:

工作階段權杖。例如,如果將 <sessionState> 元素的 mode 屬性設定為 InProcSQLServerStateServer,來啟用工作階段狀態,則 ASP.NET 會自動產生此權杖。

注意 您可以覆寫 <sessionState> 設定,以及在 @Page 標籤上使用 EnableSessionState 屬性,來逐頁停用或啟用工作階段狀態。

驗證權杖。這是由驗證機制產生,例如表單驗證,來追蹤驗證的使用者的工作階段。利用有效的驗證權杖,使用者就可以取得網站受限制部份的存取權。

下列建議有助於您建立安全工作階段管理:

機密網頁需要驗證

不要依賴用戶端狀態管理選項

不要混合工作階段權杖和驗證權杖

有效使用 SSL

保障工作階段資料的安全

機密網頁需要驗證

在允許使用者存取機密和網站的受限制部份之前,務必先驗證使用者。如果您使用安全驗證並以 SSL 保護驗證權杖,則使用者的工作階段是安全的,因為攻擊者無法劫持及重新執行工作階段權杖。攻擊者需要驗證權杖才能通過授權大門。

有關如何保障驗證權杖安全以進行表單驗證的詳細資訊,請參閱本單元前面的「表單驗證」。

不要依賴用戶端狀態管理選項

避免使用任何用戶端狀態管理選項來儲存機密資料,如檢視狀態、Cookie、查詢字串或隱藏式表單欄位。此資訊可能遭到竄改或以純文字方式檢視。使用伺服器端狀態管理選項 (例如,資料庫) 來儲存機密資料。

不要混合工作階段權杖和驗證權杖

安全工作階段管理要求不得混合兩種權杖類型。首先,保障驗證權杖的安全,以確定攻擊者無法擷取它及使用它來取得應用程式受限制區域的存取權。其次,建立應用程式時,應該使得他人無法單獨使用工作階段權杖來取得機密網頁或資料的存取權。工作階段權杖應該只用於個人化用途,或於多個 HTTP 要求中維護使用者狀態。若無驗證,請勿維護使用者狀態的機密項目。

有效使用 SSL

如果網站有安全區域和共用存取區域,您必須以 SSL 保護安全驗證區域。當使用者往返於安全區域和公用區域之間,ASP.NET – 產生的工作階段 Cookie (或 URL,如果您已啟用 cookie-less 工作階段狀態) 會以純文字方式隨之移動,但只要有設定 Secure cookie 內容,就絕不會透過未加密的 HTTP 連線傳送驗證 Cookie。

注意 您可以透過在 <forms> 元素上設定 requireSSL="true" ,來設定表單驗證 Cookie 的 Secure 內容。

攻擊者可能透過未加密的 HTTP 工作階段取得工作階段 Cookie,但如果您已正確設定網站,並將受限制網頁和資源放在不同的安全目錄下,則攻擊者只能用它來存取不安全的公用存取網頁。此情況並無安全上的威脅,因為這些網頁不執行機密作業。一旦攻擊者試圖在安全網頁上重新執行工作階段權杖時,由於沒有驗證權杖,攻擊者將重新導向應用程式的登入網頁。

有關使用 Secure cookie 內容以及如何建立安全表單驗證解決方案的詳細資訊,請參閱本單元前面的「表單驗證」。

保障工作階段資料的安全

如果伺服器上的工作階段資料包含機密項目,則需要保障資料和存放區的安全。ASP.NET 支援數個工作階段狀態模式。有關如何保障 ASP.NET 工作階段狀態的安全的資訊,請參閱單元 19<保障 ASP.NET 應用程式及 Web 服務的安全>中的「工作階段狀態」。

回到頁首回到頁首

參數操作

攻擊者可能操作在表單欄位、查詢字串、檢視狀態和 Cookie 等所找到的那些參數,企圖取得受限制網頁的存取權,或欺騙應用程式去執行未授權的作業。

例如,如果攻擊者知道您使用安全性不足的驗證權杖方式,例如 Cookie 中一個猜得到的數字,攻擊者可以用另一個數字建構 Cookie,並以另一個 (可能有特殊權限) 使用者提出要求。

下列建議有助於避免參數操作弱點:

使用 MAC 保護檢視狀態

使用 Page.ViewStateUserKey 反制一次點選攻擊

在伺服器上維護機密資料

驗證輸入參數

使用 MAC 保護檢視狀態

如果網頁或控制項使用檢視狀態來維護 HTTP 要求中的狀態,請確定檢視狀態已加密,並透過 MAC 的使用來檢查其完整性。在預設的狀況下,Machine.config 內的 <pages> 元素上的 enableViewStateMac 屬性可確保檢視狀態得到 MAC 的保護。

<pages buffer="true" enableSessionState="true"
enableViewState="true" enableViewStateMac="true" 
autoEventWireup="true" validateRequest="true"/>

注意 @Page 指示詞亦支援之前的屬性,可讓您逐頁自訂設定。

雖然您可以覆寫檢視狀態是逐一控制項、逐一網頁或逐一應用程式啟用,但每當您使用檢視狀態時,請確定 enableViewStateMac 是設定為 true。

Server.Transfer

如果應用程式使用 Server.Transfer ,如下所示,並設定選用的第二個布林參數為 true,使得 QueryString Form 集合得以保留,但如果 enableViewStateMac 是設定為 true,則此命令失敗。

Server.Transfer("page2.aspx", true);

如果您省略第二個參數,或將它設為 False,則不發生錯誤。如果您想要保留 QueryString Form 集合,而不要設定 enableViewStateMac 為 false,請遵照 Microsoft Knowledge Base 文章 316920《PRB: "View State Is Invalid" Error Message When You Use Server.Transfer (英文)》所討論的因應措施。

關於對檢視狀態加密和完整性檢查設定 <machineKey> 元素的資訊,請參閱單元 19<保障 ASP.NET 應用程式及 Web 服務的安全>。

使用 Page.ViewStateUserKey 反制一次點選攻擊

如果您驗證呼叫者及使用檢視狀態,請在 Page_Init 事件控制碼中設定 Page.ViewStateUserKey 內容,以防止一次點選攻擊。當攻擊者在檢視狀態下建立一個預先填妥的網頁 (.htm 或 .aspx),即發生一次點選攻擊。檢視狀態可從攻擊者先前建立的網頁中產生,例如,含有 100 個項目的購物車網頁。攻擊者引誘使用者瀏覽該網頁,然後將網頁傳送至檢視狀態有效的伺服器。伺服器無法得知檢視狀態是從攻擊者產生。檢視狀態驗證和 MAC 不反制此攻擊,因為檢視狀態有效,且該網頁是在使用者的安全性內容下執行。

Page.ViewStateUserKey 內容設定為適當的唯一值,作為一次點選攻擊的因應對策。此值對每一個使用者而言應該是唯一的,且通常是使用者名稱或識別元。當攻擊者建立檢視狀態時,ViewStateUserKey 內容會起始設定為他或她的名稱。當使用者提交網頁至伺服器時,它會起始設定為攻擊者的名稱。因此,檢視狀態 MAC 檢查失敗,並產生例外狀況。

注意 此攻擊對匿名瀏覽的網頁 (沒有使用者名稱可用) 通常不會構成問題,因為此種網頁不會進行機密交易。

在伺服器維護機密資料

不要信任輸入參數,尤其當它們使用於伺服器做安全性決策時。同時,不要對任何形式的機密資料使用純文字參數。相反地,請將機密資料儲存在工作階段存放區上,並使用工作階段權杖來參照存放區的項目。確定使用者已通過安全驗證,且驗證權杖受到安全保護。如需詳細資訊,請參閱本單元前面的「工作階段管理」。

驗證輸入參數

驗證所有來自表單欄位、查詢字串、Cookie 和 HTTP 標頭的輸入參數。System.Text.RegularExpressions.Regex 類別協助驗證輸入參數。例如,下列程式碼顯示如何使用此類別來驗證透過查詢字串參數傳送的名稱。相同技術可用來驗證其他形式的輸入參數,例如 cookie 或表單欄位。例如,若要驗證 cookie 參數,請使用 Request.Cookies 代替 Request.QueryString

using System.Text.RegularExpressions;
. . .
private void Page_Load(object sender, System.EventArgs e)
{
// 名稱必須包含 1 到 40 個英數字元,
// 以及 (選擇性地) 特殊字元 '`?,例如像
// D'Angelo 這樣的名稱
if (!Regex.IsMatch(Request.QueryString["name"], 
@"^[\p{L}\p{Zs}\p{Lu}\p{Ll}]{1,40}$"))
throw new Exception("Invalid name parameter");
// 使用個別規則運算式來驗證所有其他
// 查詢字串參數
  . . .
}

有關如何使用規則運算式和驗證輸入資料的詳細資訊,請參閱本單元前面的「輸入驗證」。

回到頁首回到頁首

例外管理

網頁的正確例外處理可防止機密例外詳細資料洩露給使用者。下列建議適用於 ASP.NET 網頁和控制項。

傳回一般錯誤網頁給用戶端

實作網頁層級或應用程式層級錯誤控制碼

有關例外管理的詳細資訊,請參閱單元 7<建置安全的組件>。

傳回一般錯誤網頁給用戶端

萬一有尚未處理的例外,亦即傳入應用程式界限的例外,會傳回一般錯誤網頁給使用者。若要這麼做,請如下設定 <customErrors> 元素:

<customErrors mode="On" defaultRedirect="YourErrorPage.htm" />

錯誤網頁應包括適當的一般錯誤訊息,可能還有其他支援詳細資料。產生錯誤的網頁名稱會透過 aspxerrorpath 查詢參數傳送至錯誤網頁。

您也可以針對不同錯誤類型使用多種錯誤網頁。例如:

<customErrors mode="On" defaultRedirect="YourErrorPage.htm">
<error statusCode="404" redirect="YourNotFoundPage.htm"/>              
<error statusCode="500" redirect="YourInternalErrorPage.htm"/>              
</customErrors>

對於個別網頁,您可以使用下列網頁層級屬性來提供錯誤網頁:

<% @ Page ErrorPage="YourErrorPage" %>

實作網頁層級或應用程式層級錯誤控制碼

如果您需要在網頁層級擷取及處理未處理的例外,請針對 Page_Error 事件建立控制碼,類似以下所顯示。

public void Page_Error(object sender,EventArgs e)
{
// 取得來源例外詳細資料
Exception ex = Server.GetLastError();
// 撰寫詳細資料至事件日誌中以進行診斷
  . . .
// 防止例外傳入及產生
// 應用程式層級事件 (Application.Error)
Server.ClearError();
}  

如果允許例外從網頁控制碼傳入,或沒有網頁控制碼,則會發生應用程式錯誤事件。若要設陷應用程式層級事件,請在 Global.asax 實作 Application_Error ,如下所示:

protected void Application_Error(Object sender, EventArgs e) 
{
//  寫至事件日誌。
}
回到頁首回到頁首

稽核和記錄

Web 應用程式的預設 ASP.NET 處理序識別身份可以在事件日誌中撰寫新記錄,但它沒有足夠權限建立新事件的來源。若要解決此問題,您有兩個選擇。您可以建立安裝程式類別,當具備系統管理員權限時,可在安裝時期呼叫此類別,或者,您可以在 EventLog 登錄機碼上設定權限,允許 ASP.NET 處理序識別身份 (或模擬式識別身份) 在執行時期建立事件來源。建議使用前一種方式。

若要在安裝時期建立應用程式事件來源

1.

在 Visual Studio .NET 的 Solution Explorer 視窗中,在您的專案上按一下滑鼠右鍵,指向 [新增 (Add)],然後按一下 [新增元件 (Add Component)]。

2.

從範本清單中選取 [安裝程式類別 (Installer Class)],並提供適當的類別檔名。

這樣會建立一個新的安裝程式類別,並以 RunInstaller(true) 屬性作為附注。

RunInstaller(true)
public class EventSourceInstaller : System.Configuration.Install.Installer
{
 . . .
}

3.

在 [設計 (Design)] 檢視中顯示新的安裝程式類別,顯示「工具箱」,然後按一下「工具箱」中的 [元件 (Components)]。將 EventLogInstaller 元件拖曳至 Designer 工作平面。

注意 如果 EventLogInstaller 未出現在工具箱,請在工具箱上按一下滑鼠右鍵,然後按一下 [新增/移除項目 (Add/Remove Items)]。然後選取 EventLogInstaller 來新增此元件類型。

4.

設定下列 EventLogInstaller 內容:

Log。設定此內容為 "Application" ,它是您應該使用的事件日誌名稱。您可以使用預設 Application 日誌,或建立應用程式專用日誌。

Source。設定此內容為事件來源名稱。這通常是指應用程式名稱。

5.

建立專案,然後在安裝時期建立安裝程式類別的例項。

如果您使用 .NET Setup and Deployment 專案來建立 Windows 安裝程式檔 (.msi),則會自動建立及呼叫 Installer 類別例項。如果您使用 xcopy 或同等部署,請使用 InstallUtil.exe 公用程式建立安裝程式類別的例項並執行它。

6.

若要確認事件來源成功產生,請使用系統登錄編輯器並瀏覽至:

HKLM\System\CurrentControlSet\Services\EventLog\Application\{source name}

確認此機碼存在,且它包含 EventMessageFile 字串值,指向預設 .NET Framework 事件訊息檔:

\Windows\Microsoft.NET\Framework\{version}\EventLogMessages.dll

如果您有現有的應用程式,不想建立安裝程式類別,您必須授與 ASP.NET 處理序識別身份正確的存取權,來存取事件日誌登錄機碼。關於登錄機碼詳細資料和必要的正確存取權,請參閱單元 19<保障 ASP.NET 應用程式及 Web 服務的安全>的「事件日誌」。

EventLogPermission

寫入事件日誌中的程式碼必須由程式碼存取安全性原則授與 EventLogPermission。如果 Web 應用程式是設定為在部分信任等級執行,則這會是個問題。有關如何從部分信任的 Web 應用程式中寫入事件日誌的詳細資訊,請參閱單元 9<配合 ASP.NET 使用程式碼存取安全性>。

回到頁首回到頁首

總結

本單元一開始是介紹您在建立網頁和控制項時需要對付的主要潛在威脅。許多應用程式層級的攻擊是依賴輸入驗證的弱點。請特別留意這方面,確定驗證策略健全,且從不信任來源處理的所有資料已適當驗證過。另一個常見的弱點是未能保護驗證 Cookie。本單元的「表單驗證」一節顯示可套用的有效因應對策,以防止未授權者存取、連線劫持和 Cookie 重新執行等攻擊。

回到頁首回到頁首

其他資源

有關其他詳細資訊,請參閱下列資源:

有關建立安全 Machine.config 和 Web.config 設定的詳細資訊,請參閱單元 19<保障 ASP.NET 應用程式及 Web 服務的安全>。

如需可列印的檢查清單,請參閱本指南<檢查清單>一節中的<檢查清單:保障 ASP.NET 的安全>。

如需保障開發人員工作站安全的詳細資訊,請參閱本指南<How To>一節中的<How To:保障開發人員工作站的安全>。

如需 ASP.NET 中的驗證和授權的詳細資訊,請參閱《Microsoft patterns & practices Volume I, Building Secure ASP.NET Web Applications: Authentication, Authorization, and Secure Communication (英文)》的單元 8<ASP.NET 安全性>,網址是:http://msdn.microsoft.com/library/en-us/dnnetsec/html/SecNetch08.asp

有關使用表單驗證的逐步解說,請參閱《Microsoft patterns & practices Volume I, Building Secure ASP.NET Web Applications: Authentication, Authorization, and Secure Communication (英文)》的<How To>一節中的<How To: Use Forms Authentication with SQL Server 2000>及<How To: Use Forms Authentication with Active Directory>,網址是:http://msdn.microsoft.com/library/en-us/dnnetsec/html/SecNetHT00.asp

有關使用規則運算式的詳細資訊,請參閱 Microsoft Knowledge Base 文章 308252《How To: Match a Pattern by Using Regular Expressions and Visual C# .NET (英文)》

有關 ASP.NET 中的使用者輸入驗證的詳細資訊,請參閱 MSDN 文章《User Input Validation in ASP.NET (英文)》,網址是:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/pdc_userinput.asp

有關 Secure Cookie 內容的詳細資訊,請參閱 W3C 網站上的 RFC2109,網址是:http://www.w3.org/Protocols/rfc2109/rfc2109

有關 Open Hack 競賽中安全性考量的詳細資訊,請參閱 MSDN 文章《Building and Configuring More Secure Web Sites (英文)》,網址是:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/openhack.asp


回到頁首回到頁首