共用方式為


保護連接字串與其他設定資訊 (C#)

由斯科特· 米切爾

下載 PDF

ASP.NET 應用程式通常會將組態資訊儲存在 Web.config 檔案中。 其中一些資訊是敏感性的,而且需要保護。 根據預設,此檔案不會提供給網站訪客,但系統管理員或駭客可能會取得網頁伺服器檔系統的存取權,並檢視檔案的內容。 在本教學課程中,我們瞭解 ASP.NET 2.0 可讓我們藉由加密 Web.config 檔案的區段來保護敏感性資訊。

簡介

ASP.NET 應用程式的組態資訊通常會儲存在名為 Web.config的 XML 檔案中。 在這些教學課程中,我們更新 Web.config 了幾次。 例如,在第一個教學課程中建立Northwind具類型的 DataSet 時,連接字串 一節中<connectionStrings>會自動新增Web.config資訊。 稍後,在主版頁面和網站導覽教學課程中,我們會手動更新 Web.config,並新增<pages>元素,指出專案中的所有 ASP.NET 頁面都應該使用DataWebControls主題。

由於Web.config可能包含敏感數據,例如 連接字串,因此請務必將 的內容Web.config從未經授權的檢視者中保持安全且隱藏。 根據預設,擴展名為 .config 檔案的任何 HTTP 要求都會由 ASP.NET 引擎處理,這會傳回 此類型的頁面未提供 如圖 1 所示的訊息。 這表示訪客無法直接輸入http://www.YourServer.com/Web.config瀏覽器的網址列來檢視您的Web.config檔案內容。

流覽 Web.config 透過瀏覽器傳回此類型的頁面未提供訊息

圖 1:瀏覽 Web.config 瀏覽器 傳回此類型的頁面未提供訊息 (按兩下以檢視完整大小的影像

但是,如果攻擊者能夠找到一些其他惡意探索,讓她能夠檢視檔案 Web.config 的內容,該怎麼辦? 攻擊者可以使用這項資訊做什麼,以及可以採取哪些步驟來進一步保護內的 Web.config敏感性資訊? 幸運的是,中的 Web.config 大部分區段不包含敏感性資訊。 如果攻擊者知道您 ASP.NET 頁面所使用的預設主題名稱,攻擊者可能會造成什麼傷害?

不過,某些Web.config區段包含可能包含 連接字串、使用者名稱、密碼、伺服器名稱、加密密鑰等敏感性資訊。 此資訊通常會在下列 Web.config 各節中找到:

  • <appSettings>
  • <connectionStrings>
  • <identity>
  • <sessionState>

在本教學課程中,我們將探討保護這類敏感性組態信息的技術。 如我們所見,.NET Framework 2.0 版包含受保護的組態系統,讓以程序設計方式加密和解密選取的組態區段變得微風。

注意

本教學課程最後將探討從 ASP.NET 應用程式連線到資料庫Microsoft的建議。 除了加密 連接字串 之外,您還可以確保以安全的方式連線到資料庫,協助強化系統。

步驟 1:探索 ASP.NET 2.0 s 受保護的組態選項

ASP.NET 2.0 包含受保護的組態系統,用於加密和解密組態資訊。 這包括 .NET Framework 中可用來以程序設計方式加密或解密組態資訊的方法。 受保護的組態系統會使用提供者模型,讓開發人員選擇使用的密碼編譯實作。

.NET Framework 隨附兩個受保護的組態提供者:

由於受保護的組態系統會實作提供者設計模式,因此可以建立您自己的受保護組態提供者,並將其插入您的應用程式。 如需此程式的詳細資訊,請參閱 實作受保護的設定提供者

RSA 和 DPAPI 提供者會使用金鑰進行加密和解密例程,而且這些密鑰可以儲存在電腦或使用者層級。 計算機層級金鑰適用於 Web 應用程式在其專屬伺服器上執行,或伺服器上有多個應用程式需要共用加密信息的情況。 在共用裝載環境中,用戶層級密鑰是更安全的選項,相同伺服器上的其他應用程式不應該能夠解密應用程式受保護的組態區段。

在本教學課程中,我們的範例會使用 DPAPI 提供者和機器層級密鑰。 具體而言,我們將探討加密 <connectionStrings> 中的 Web.config區段,雖然受保護的組態系統可用來加密大部分的任何 Web.config 區段。 如需有關使用用戶層級密鑰或使用 RSA 提供者的資訊,請參閱本教學課程結尾一節中的資源。

注意

RSAProtectedConfigurationProviderDPAPIProtectedConfigurationProvider 提供者會分別在檔案中machine.config註冊提供者名稱和 RsaProtectedConfigurationProvider DataProtectionConfigurationProvider。 加密或解密組態資訊時,我們需要提供適當的提供者名稱(RsaProtectedConfigurationProviderDataProtectionConfigurationProvider),而不是實際的類型名稱 (RSAProtectedConfigurationProviderDPAPIProtectedConfigurationProvider)。 您可以在資料夾中找到 machine.config 檔案 $WINDOWS$\Microsoft.NET\Framework\version\CONFIG

步驟 2:以程式設計方式加密和解密組態區段

透過幾行程式代碼,我們可以使用指定的提供者來加密或解密特定組態區段。 如我們很快就會看到的程序代碼,只需要以程式設計方式參考適當的組態區段、呼叫其 ProtectSectionUnprotectSection 方法,然後呼叫 Save 方法來保存變更。 此外,.NET Framework 也包含實用的命令行公用程式,可加密和解密組態資訊。 我們將在步驟 3 中探索此命令行公用程式。

為了說明以程式設計方式保護組態資訊,讓我們建立 ASP.NET 頁面,其中包含用於加密和解密 <connectionStrings> 中的 Web.config區段的按鈕。

從開啟 EncryptingConfigSections.aspx 資料夾中的頁面 AdvancedDAL 開始。 將 TextBox 控制件從 [工具箱] 拖曳至 [設計工具],將其 ID 屬性設定為 WebConfigContents、將其 TextMode 屬性 MultiLine分別拖曳至 ,並將 和 Width Rows 屬性分別拖曳至 95% 和 15。 此 TextBox 控制件會顯示允許我們快速查看內容是否已加密的內容 Web.config 。 當然,在實際的應用程式中,您絕不會想要顯示 的內容 Web.config

在 TextBox 底下,新增兩個名為 EncryptConnStrings 和的 DecryptConnStringsButton 控件。 將其 Text 屬性設定為 [加密連接字串] 和 [解密連接字串]。

此時,您的畫面看起來應該類似圖 2。

此螢幕快照顯示 Visual Studio 已開啟至 [EncryptingConfigSections.aspx] 頁面,其中包含新的 TextBox 和兩個 Button 控件。

圖 2:將 TextBox 和兩個按鈕 Web 控件新增至頁面(按兩下以檢視完整大小的影像

接下來,我們需要撰寫程序代碼,以在第一次載入頁面時,載入並顯示 TextBox 中WebConfigContents的內容Web.config。 將下列程式代碼新增至頁面的程式代碼後置類別。 當 為 falsePage.IsPostBack,此程式代碼會新增名為 DisplayWebConfig 的方法,Page_Load並從事件處理程式呼叫它:

protected void Page_Load(object sender, EventArgs e)
{
    // On the first page visit, call DisplayWebConfig method
    if (!Page.IsPostBack)
        DisplayWebConfig();
}
private void DisplayWebConfig()
{
    // Reads in the contents of Web.config and displays them in the TextBox
    StreamReader webConfigStream = 
        File.OpenText(Path.Combine(Request.PhysicalApplicationPath, "Web.config"));
    string configContents = webConfigStream.ReadToEnd();
    webConfigStream.Close();
    WebConfigContents.Text = configContents;
}

DisplayWebConfig方法會File使用 類別來開啟應用程式檔案Web.configStreamReader類別的內容讀入字串,以及Path類別以產生檔案的實體路徑。Web.config 這三個類別全都位於 命名空間System.IO。 因此,您必須將語句新增usingSystem.IO至程式代碼後置類別頂端,或者,將這些類別名稱前面加上 System.IO.

接下來,我們需要新增兩個 Button 控制項 Click 事件的事件處理程式,並新增必要的程式代碼,以使用電腦層級密鑰搭配 DPAPI 提供者來加密和解密 <connectionStrings> 區段。 在設計工具中,按兩下每個 Buttons,在程式代碼後置類別中新增 Click 事件處理程式,然後新增下列程式代碼:

protected void EncryptConnStrings_Click(object sender, EventArgs e)
{
    // Get configuration information about Web.config
    Configuration config = 
        WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath);
    // Let's work with the <connectionStrings> section
    ConfigurationSection connectionStrings = config.GetSection("connectionStrings");
    if (connectionStrings != null)
        // Only encrypt the section if it is not already protected
        if (!connectionStrings.SectionInformation.IsProtected)
        {
            // Encrypt the <connectionStrings> section using the 
            // DataProtectionConfigurationProvider provider
            connectionStrings.SectionInformation.ProtectSection(
                "DataProtectionConfigurationProvider");
            config.Save();
            
            // Refresh the Web.config display
            DisplayWebConfig();
        }
}
protected void DecryptConnStrings_Click(object sender, EventArgs e)
{
    // Get configuration information about Web.config
    Configuration config = 
        WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath);
    // Let's work with the <connectionStrings> section
    ConfigurationSection connectionStrings = 
        config.GetSection("connectionStrings");
    if (connectionStrings != null)
        // Only decrypt the section if it is protected
        if (connectionStrings.SectionInformation.IsProtected)
        {
            // Decrypt the <connectionStrings> section
            connectionStrings.SectionInformation.UnprotectSection();
            config.Save();
            // Refresh the Web.config display
            DisplayWebConfig();
        }
}

兩個事件處理程式中使用的程式代碼幾乎完全相同。 兩者一開始都是透過 WebConfigurationManager 類別 s OpenWebConfiguration 方法取得目前應用程式Web.config檔案的相關信息。 這個方法會傳回指定之虛擬路徑的 Web 組態檔。 接下來,Web.config檔案 s 區段是透過 Configuration 類別 s <connectionStrings>GetSection(sectionName) 方法來存取,這個方法ConfigurationSection傳回 物件。

物件ConfigurationSection包含屬性SectionInformation,提供有關組態區段的其他資訊和功能。 如上述程式代碼所示,我們可以藉由檢查 SectionInformation 屬性的 IsProtected 屬性來判斷組態區段是否已加密。 此外,區段可以透過 SectionInformation 屬性和 ProtectSection(provider) UnprotectSection 方法來加密或解密。

方法 ProtectSection(provider) 接受做為輸入字串,指定加密時要使用的受保護組態提供者名稱。 在 Button 事件處理程式中 EncryptConnString ,我們會將 DataProtectionConfigurationProvider 傳遞至 ProtectSection(provider) 方法,以便使用 DPAPI 提供者。 方法 UnprotectSection 可以判斷用來加密組態區段的提供者,因此不需要任何輸入參數。

呼叫 ProtectSection(provider)UnprotectSection 方法之後,您必須呼叫 Configuration 物件 s Save 方法來 保存變更。 設定資訊經過加密或解密並儲存變更之後,我們會呼叫 DisplayWebConfig 以將更新 Web.config 的內容載入 TextBox 控制件。

輸入上述程式代碼之後,請透過瀏覽器瀏覽 EncryptingConfigSections.aspx 頁面來測試它。 您一開始應該會看到一個頁面,其中列出以純文本顯示的區段內容Web.config<connectionStrings>(請參閱圖 3)。

顯示網頁瀏覽器中載入EncryptingConfigSections.aspx頁面的螢幕快照。

圖 3:將 TextBox 和兩個按鈕 Web 控件新增至頁面(按兩擊以檢視完整大小的影像

現在,按兩下 [加密連接字串] 按鈕。 如果啟用要求驗證,則從 WebConfigContents TextBox 回傳的標記會產生 HttpRequestValidationException,其會顯示訊息:從客戶端偵測到潛在的危險 Request.Form 值。 根據預設,ASP.NET 2.0 中啟用的要求驗證會禁止包含未編碼 HTML 的回傳,並設計來協助防止腳本插入式攻擊。 此檢查可以在頁面或應用層級停用。 若要關閉此頁面的設定,請將 ValidateRequest 指示詞中的 @Page 設定false設為 。 指示 @Page 詞位於頁面宣告式標記的頂端。

<%@ Page ValidateRequest="False" ... %>

如需要求驗證的詳細資訊、其用途、如何在頁面和應用層級停用它,以及如何 HTML 編碼標記,請參閱 要求驗證 - 防止腳本攻擊

停用頁面的要求驗證之後,請嘗試再次按兩下 [加密連接字串] 按鈕。 在回傳時,將會存取組態檔,並使用 DPAPI 提供者加密其 <connectionStrings> 區段。 接著會更新 TextBox 以顯示新 Web.config 內容。 如圖 4 所示, <connectionStrings> 信息現在已加密。

按兩下 [加密連接字串] 按鈕 [ <加密 connectionString> ] 區段

圖 4:按兩下 [加密連接字串] 按鈕加密 <connectionString> 區段 (按兩下以檢視完整大小的影像

我的計算機上產生的加密 <connectionStrings> 區段會遵循,不過元素中的 <CipherData> 部分內容已移除,以求簡潔:

<connectionStrings 
    configProtectionProvider="DataProtectionConfigurationProvider">
  <EncryptedData>
    <CipherData>
      <CipherValue>AQAAANCMnd8BFdERjHoAwE/...zChw==</CipherValue>
    </CipherData>
  </EncryptedData>
</connectionStrings>

注意

元素 <connectionStrings> 會指定用來執行加密的提供者(DataProtectionConfigurationProvider)。 按兩下 [解密連接字串] 按鈕時,方法會使用 UnprotectSection 這項資訊。

從存取 連接字串 資訊Web.config時- 由我們撰寫的程式代碼、從 SqlDataSource 控件,或從 Typed DataSets 中的 TableAdapters 自動產生程式代碼時,系統會自動解密。 簡言之,我們不需要新增任何額外的程式代碼或邏輯來解密加密的 <connectionString> 區段。 若要示範這一點,請流覽目前先前的其中一個教學課程,例如基本報告一節的簡單顯示教學課程(~/BasicReporting/SimpleDisplay.aspx)。 如圖 5 所示,本教學課程的運作方式與預期完全相同,指出 ASP.NET 頁面會自動解密加密 連接字串 資訊。

數據存取層會自動解密連接字串資訊

圖 5:資料存取層會自動解密連接字串資訊(按兩下以檢視完整大小的影像

若要將 <connectionStrings> 區段還原回其純文本表示法,請按兩下 [解密連接字串] 按鈕。 在回傳時,您應該會看到純文本中的 Web.config 連接字串。 此時,您的畫面看起來應該像第一次瀏覽此頁面時所做的一樣(如圖 3 所示)。

步驟 3:使用 aspnet_regiis.exe 加密組態區段

.NET Framework 包含資料夾中的各種命令行工具 $WINDOWS$\Microsoft.NET\Framework\version\ 。 例如,在使用 SQL 快取相依性 教學課程中,我們查看了使用 aspnet_regsql.exe 命令行工具來新增 SQL 快取相依性所需的基礎結構。 此資料夾中另一個實用的命令行工具是 ASP.NET IIS 註冊工具 (aspnet_regiis.exe。 正如其名所示,ASP.NET IIS 註冊工具主要用於向Microsoft專業級 Web 伺服器 IIS 註冊 ASP.NET 2.0 應用程式。 除了 IIS 相關功能之外,ASP.NET IIS 註冊工具也可用來加密或解密 中的 Web.config指定組態區段。

下列語句顯示使用命令列工具加密組態區段 aspnet_regiis.exe 的一般語法:

aspnet_regiis.exe -pef section physical_directory -prov provider

section 是加密的組態區段(例如 connectionStrings), physical_directory 是 Web 應用程式根目錄的完整實體路徑,而 提供者 是要使用的受保護組態提供者名稱(例如 DataProtectionConfigurationProvider)。 或者,如果 Web 應用程式已在 IIS 中註冊,您可以使用下列語法來輸入虛擬路徑,而不是實體路徑:

aspnet_regiis.exe -pe section -app virtual_directory -prov provider

下列 aspnet_regiis.exe 範例會使用 DPAPI 提供者搭配電腦層級金鑰來加密 <connectionStrings> 區段:

aspnet_regiis.exe -pef
"connectionStrings" "C:\Websites\ASPNET_Data_Tutorial_73_CS"
-prov "DataProtectionConfigurationProvider"

同樣地, aspnet_regiis.exe 命令行工具也可以用來解密組態區段。 -pef不使用 參數,請使用 -pdf (或 ,而不是 -pe使用 -pd)。 此外,請注意,解密時不需要提供者名稱。

aspnet_regiis.exe -pdf section physical_directory
  -- or --
aspnet_regiis.exe -pd section -app virtual_directory

注意

因為我們使用的是 DPAPI 提供者,其使用電腦特定的金鑰,因此您必須從提供網頁的相同電腦執行 aspnet_regiis.exe 。 例如,如果您從本機開發計算機執行此命令行程式,然後將加密的 Web.config 檔案上傳至實際執行伺服器,則生產伺服器將無法解密 連接字串 資訊,因為它使用開發電腦專屬的密鑰加密。 RSA 提供者沒有這項限制,因為可以將 RSA 金鑰匯出至另一部電腦。

瞭解資料庫驗證選項

任何應用程式都必須先識別要求者,才能對Microsoft SQL Server 資料庫發出 SELECTINSERTUPDATEDELETE 查詢。 此程式稱為 驗證 ,SQL Server 提供兩種驗證方法:

  • Windows 驗證 - 應用程式執行的程式是用來與資料庫通訊。 透過 Visual Studio 2005 s ASP.NET Development Server 執行 ASP.NET 應用程式時,ASP.NET 應用程式會假設目前登入使用者的身分識別。 針對 Microsoft Internet Information Server (IIS) 上的 ASP.NET 應用程式,ASP.NET 應用程式通常會假設 或domainName``\NETWORK SERVICEdomainName``\MachineName身分識別,但可以自定義。
  • SQL 驗證 - 使用者識別碼和密碼值會提供作為驗證的認證。 使用 SQL 驗證時,使用者識別碼和密碼會在 連接字串 中提供。

Windows 驗證 優先於 SQL 驗證,因為它更安全。 使用 Windows 驗證,連接字串 可從使用者名稱和密碼中釋出,如果網頁伺服器和資料庫伺服器位於兩部不同的計算機上,則認證不會以純文本透過網路傳送。 不過,使用 SQL 驗證時,驗證認證會在 連接字串 中硬式編碼,並以純文本形式從網頁伺服器傳輸至資料庫伺服器。

這些教學課程已使用 Windows 驗證。 您可以藉由檢查 連接字串 來判斷正在使用的驗證模式。 我們的教學課程 連接字串 Web.config 已:

Data Source=.\SQLEXPRESS; AttachDbFilename=|DataDirectory|\NORTHWND.MDF; Integrated Security=True; User Instance=True

整合式安全性=True 且缺少使用者名稱和密碼,表示正在使用 Windows 驗證。 在某些 連接字串 使用 Trusted Connection=Yes 或 Integrated Security=SSPI 一詞,而不是整合式安全性=True,但這三個都表示使用 Windows 驗證。

下列範例顯示使用 SQL 驗證的 連接字串。 $CREDENTIAL_PLACEHOLDER$ 是密碼機碼/值組的佔位元。 請注意,認證會內嵌在 連接字串 中:

Server=serverName; Database=Northwind; uid=userID; $CREDENTIAL_PLACEHOLDER$

假設攻擊者能夠檢視您的應用程式 Web.config 檔案。 如果您使用 SQL 驗證連線到可透過因特網存取的資料庫,攻擊者可以使用此 連接字串 透過 SQL Management Studio 或從自己的網站上 ASP.NET 頁面連線到您的資料庫。 若要協助減輕此威脅,請使用受保護的組態系統加密 中的 Web.config 連接字串 資訊。

注意

如需 SQL Server 中可用之不同驗證類型的詳細資訊,請參閱 建置安全 ASP.NET 應用程式:驗證、授權和安全通訊。 如需進一步的 連接字串 範例,說明 Windows 和 SQL 驗證語法之間的差異,請參閱 ConnectionStrings.com

摘要

根據預設,ASP.NET 應用程式中擴展名 .config 為的檔案無法透過瀏覽器存取。 這些類型的檔案不會傳回,因為它們可能包含敏感性資訊,例如資料庫 連接字串、使用者名稱和密碼等等。 .NET 2.0 中受保護的組態系統可讓指定的組態區段加密,以協助進一步保護敏感性資訊。 有兩個內建的受保護組態提供者:一個使用 RSA 演算法,另一個使用 Windows 數據保護 API (DPAPI)。

在本教學課程中,我們探討如何使用 DPAPI 提供者來加密和解密組態設定。 這可以透過程序設計方式完成,如我們在步驟 2 中所見,以及透過 aspnet_regiis.exe 步驟 3 所涵蓋的命令行工具來完成。 如需改用用戶層級密鑰或使用 RSA 提供者的詳細資訊,請參閱進一步閱讀一節中的資源。

快樂的程序設計!

深入閱讀

如需本教學課程中所討論主題的詳細資訊,請參閱下列資源:

關於作者

斯科特·米切爾,七本 ASP/ASP.NET 書籍和 4GuysFromRolla.com 創始人的作者,自1998年以來一直與Microsoft Web 技術合作。 斯科特擔任獨立顧問、教練和作家。 他的最新書是 山姆斯在24小時內 ASP.NET 2.0。 他可以到達 mitchell@4GuysFromRolla.com, 或通過他的博客,可以在 找到 http://ScottOnWriting.NET

特別感謝

本教學課程系列已由許多實用的檢閱者檢閱。 本教學課程的主要檢閱者是 Teresa Murphy 和 Randy Schmidt。 有興趣檢閱我即將推出的 MSDN 文章嗎? 如果是,請將一行 mitchell@4GuysFromRolla.com放在 。