在Windows和Azure中使用加密證書提高web.config的安全性

weixin_33858249發表於2018-07-27
\

本文要點

\\
  • 加密證書可限制具有機密訪問許可權的人數。\\t
  • 加密證書本身並不會降低對穩健性和多層安全計劃的需求。\\t
  • pfx解密金鑰檔案必須儲存在一個安全的離線位置,並與密碼分開儲存。\\t
  • 掌握PowerShell的知識,有助於簡化認證相關的任務。\
\\

資料洩密的發生越來越頻繁,因此使應用盡可能安全是非常重要的。而web.config檔案通常以純文字形式儲存,常常缺少安全防範。一旦入侵者可以訪問該檔案,那麼就可以輕易地從內部或外部訪問資料庫和其它資源。

\\

問題並非一開始就是如此。在.NET首次推出時,很多應用執行在單個Windows域中。通常並不需要web.config檔案儲存密碼,資料庫訪問權利可以直接賦予執行應用的使用者賬戶。

\\

但對於現代應用,情況則大相徑庭。在分散式環境下,資料庫及其它資源通常執行在Windows域之外,可能並不受同一家企業的控制。在這種環境下,非常有必要正確地儲存密碼、應用令牌以及其它一些系統標識。

\\

本文介紹的技術並非最新提出的。Jouni Heikniemi在2013年的一次演講中就介紹過,SQL Azure團隊在此之前三年也做過介紹。但是這些年來,部分工具已不再推薦使用,使用者介面也在不斷地發生變化,一些特定的操作步驟不再有效。縱是如此,其中的原始概念仍然有效。

\\

增加安全性

\\

在開始介紹特定的技術之前,讀者應注重理解加密web.conf檔案的兩個方面。一是加密web.conf檔案只是應用整體安全計劃中的一個步驟;二是應瞭解加密web.conf提供了哪些方面的保護,未對哪些方面提供保護。

\\

應用要使用web.conf檔案,必須可以解密該檔案。如果將解密金鑰以檔案形式儲存在web.conf檔案旁邊,那麼顯然攻擊者會在獲取web.conf檔案時輕易獲取該檔案。如果將加密金鑰嵌入到應用中,雖然增加了一個額外步驟,但是也易於被攻破。攻擊者僅需要對竊取的程式碼執行反編譯。

\\

但是解密證書則不同。證書是儲存在作業系統層面的,攻擊者無法輕易地從硬碟中獲取。除非經使用者明確允許,否則證書甚至不可能從儲存的計算機中匯出。

\\

這並非說證書是一個完美的解決方案。如果攻擊者獲取了應用目錄的寫許可權,那麼他就可以通過更改應用去解密web.config並解讀其中的內容。這意味著,對包含應用程式碼的目錄做防寫是同等重要的。理想情況下,只有使用者的構建伺服器具備生產伺服器應用目錄的寫許可權。但是這部分內容超出了本文的範疇。

\\

另一個需要關注的問題是如何保護解密證書自身的拷貝。在建立一個新的伺服器時,需要拷貝解密證書。證書也可以離線儲存,或是儲存在其它一些安全位置。另一方面,加密證書可根據需求共享。

\\

建立加密證書

\\

加密證書類似於SSL/TLS證書,由公鑰和私鑰組成。但是加密證書是自簽名的,因為不需要驗證檔案的建立者和加密者。過去Windows開發人員需要使用makecert.exe生成證書,但是該工具目前已經不推薦使用了(雖然在Windows SDK中依然可見)。

\\

當前正確的工具是使用PowerShell在Windows機器上建立證書。建立證書的命令如下:(注意:PowerShell命令需要以管理員執行。)

\\
\$cert = New-SelfSignedCertificate -Type DocumentEncryptionCert -Subject \"CN=DevConfig\" -KeyExportPolicy Exportable -KeySpec KeyExchange\\Export-Certificate -Cert $cert -FilePath \".\\DevConfig.cer\"\\$mypwd = ConvertTo-SecureString -String \"1234\" -Force -AsPlainText\\Export-PfxCertificate -Cert $cert -FilePath \".\\DevConfig.pfx\" -Password $mypwd\\$cert
\\

如命令名稱所示,New-SelfSignedCertificate命令自身建立證書。在本例中,證書命名為“DevConfig”,使用者也可以根據個人能喜好自行定義。

\\

此後,我們使用Export-Certificate命令將加密證書匯出為“.cer”檔案。該檔案就是建立加密配置檔案所用的公鑰。

\\

其後兩行命令使用Export-PfxCertificate命令將解密證書匯出為“.pfx”檔案。需要注意的是,該檔案應該儲存在一個安全的離線位置,並與使用ConvertTo-SecureString命令定義的密碼分開儲存(當然,也要避免使用“1234”這樣不太安全的密碼)。

\\

使用者需要知道證書指紋(thumbprint),它可能會被隨後的命令所使用。最後一行命令“$cert”實現在螢幕上顯示指紋。指紋本身並不被認為是祕密的。

\\

將加密證書匯入Windows

\\

如果使用者需要配置一臺可加密配置檔案但不用解密的機器,那麼可使用如下命令。否則,跳到下一節內容。 

\\
\Import-Certificate -Filepath \".\\DevConfig.cer\" -CertStoreLocation cert:\\LocalMachine\\My
\\

詳細資訊,參見Import-Certificate文件

\\

將解密證書匯入Windows

\\

該步驟實際完成加密和解密後的證書(也就是公鑰和私鑰)的匯入。 

\\
\$mypwd = ConvertTo-SecureString -String \"1234\" -Force -AsPlainText\\Import-PfxCertificate -FilePath \".\\DevConfig.pfx\" -CertStoreLocation Cert:\\LocalMachine\\My -Password $mypwd
\\

如果使用Import-PfxCertificate命令匯入證書,那麼預設證書是不可匯出的。這意味著其他人將不能從該機器匯出證書到另一臺機器。在生產環境中最好如此配置,但是在開發機器上應標記證書為可匯出的。

\\

要驗證證書是否正確安裝,可使用Certificate Management Tool

\\

將解密證書匯入到Windows Azure

\\

對於Azure App Service,證書解密並非免費的服務。因此,下面的操作需要使用者至少具有B1層級,支援SSL連線。

\\

在Azure Portal中使用“SSL Settings”選項卡。然後點選“Upload Certificate”按鈕安裝證書。之後在螢幕下方可看到如下圖所示介面資訊:

\\

68cd80db3b53127a61892cb9f7d3bb83.png

\\

下一步,使用者需要將證書暴露給應用。具體操作是將WEBSITE_LOAD_CERTIFICATES鍵值加入到“Application Setting”選項中。使用者可以填寫以以逗號分隔的多個指紋值,或是設定值為“*”,即將使用者所有的證書暴露給Web應用。

\\

318e228c9afac382d251d1187717a38f.png

\\

提供受保護配置(Protected Configuration Provider)

\\

ProtectedConfigurationProvider實現加密和解密的處理。在本文中,我們使用了Pkcs12ProtectedConfigurationProvider。該類最初是由Microsoft建立的,併為相容Azure App Service而做了一些微小改進。

\\

對使用者程式碼而言,插入Pkcs12ProtectedConfigurationProvider到配置讀取流水線是透明的。這非常有用,使用者可以靈活地選擇使用加密還是非加密的配置檔案。

\\

使用者可以在專案中直接新增Pkcs12ProtectedConfigurationProvider,也可以通過NuGet軟體包WebConfigEncrypter下載。本文假定使用者設定了使用NuGet軟體包。

\\

設定用於加密的web.config檔案

\\

一旦專案中新增了Pkcs12ProtectedConfigurationProvider類,使用者需要設定web.config檔案實現加密。

\\

1 在web.config檔案中新增如下部分:

\\
\\u0026lt;configuration\u0026gt;\  [...]\  \u0026lt;configProtectedData\u0026gt;\    \u0026lt;providers\u0026gt;\      \u0026lt;add name=\"Pkcs12Provider\" thumbprint=\"1234123412341234123412341234123412341234\" type=\"WebConfigEncrypter.Pkcs12ProtectedConfigurationProvider, WebConfigEncrypter\" storeLocation=\"LocalMachine\"/\u0026gt;\    \u0026lt;/providers\u0026gt;\  \u0026lt;/configProtectedData\u0026gt;
\\

2 更改thumbprint屬性值為使用者證書值。

\\

3 如果使用者使用的是NuGet軟體包,那麼更新type屬性值為ProtectedConfigurationProvider DLL類的完全限定類名和程式集名。

\\

加密web.config配置中的連線串

\\

開始本步驟操作前,應確保對web.conf檔案做了備份拷貝。

\\

首先,確保aspnet命令列工具使用的是使用者的ProtectedConfigurationProvider類。在Visual Studio命令列輸入“where aspnet_regiis”。拷貝下列檔案到輸出結果指定的目錄中。

\\
  • WebConfigEncrypter.dll\\t
  • System.Configuration.ConfigurationManager.dll\\t
  • System.Security.Cryptography.Xml.dll\

然後,在web.config所在的資料夾中執行下面的命令:

\\
\aspnet_regiis -pef \"connectionStrings\" \".\" -prov \"Pkcs12Provider\"
\\

加密配置部分的內容如下:

\\
\\u0026lt;connectionStrings configProtectionProvider=\"Pkcs12Provider\"\u0026gt;\    \u0026lt;EncryptedData Type=\"http://www.w3.org/2001/04/xmlenc#Element\"\      xmlns=\"http://www.w3.org/2001/04/xmlenc#\"\u0026gt;\      \u0026lt;EncryptionMethod Algorithm=\"http://www.w3.org/2001/04/xmlenc#aes192-cbc\" /\u0026gt;\      \u0026lt;KeyInfo xmlns=\"http://www.w3.org/2000/09/xmldsig#\"\u0026gt;\        \u0026lt;EncryptedKey xmlns=\"http://www.w3.org/2001/04/xmlenc#\"\u0026gt;\          \u0026lt;EncryptionMethod Algorithm=\"http://www.w3.org/2001/04/xmlenc#rsa-1_5\" /\u0026gt;\          \u0026lt;KeyInfo xmlns=\"http://www.w3.org/2000/09/xmldsig#\"\u0026gt;\            \u0026lt;KeyName\u0026gt;rsaKey\u0026lt;/KeyName\u0026gt;\          \u0026lt;/KeyInfo\u0026gt;\          \u0026lt;CipherData\u0026gt;\            \u0026lt;CipherValue\u0026gt;Moy/a2XO2zvnn/HZW53DyC8aAJWo16+0KmnpC4SCSmuQZU0RT+HNFEA33pAGCzve+m6MTaRzhx6jVVRoAvpSNzfYG1bU1z7a1YnbW4OGxrmYYfdWW6cZQZ57dZnL6YSAlkJ5WlqPDGUPJa6FV/hTic3x4fJYy5vdSucmO6X3opuo1998LWNkL6fIS4WkjkG/SOFbI2Qx3HHogdN670jDHKNDON1z7bFHhLNyVj7RTO3xuQN9kF4PqbFtvwm1bYXTbZpdNxu/fcXZKONSAu8HN3QX5vTRyP/I4BG+NK7TUig3gxD4tq9GR7aSSGKJyt02PiCEO0JpyyIbHZ9xbck9kw==\u0026lt;/CipherValue\u0026gt;\          \u0026lt;/CipherData\u0026gt;\        \u0026lt;/EncryptedKey\u0026gt;\      \u0026lt;/KeyInfo\u0026gt;\      \u0026lt;CipherData\u0026gt;\        \u0026lt;CipherValue\u0026gt;TeV0yJaFlEhpyZUlQoG7M3O7sfQ7uG3ndgmhxipOrwoEsrI+Zvt1NI7arefOFWGNW4CEaoLo4mKy2Kwr4ZgK+6rAwOmx1IRyheWtF7z/8+CiGOqSRXLyGEkDQBEVOWKU0Y6TaWtPu0ZM3bp5pvKaztBnthgGnrGYmigaufu5rZW1GWPtHyL2iWdAkU9iaf+AOpA/GSvoVtZmnfJ1rwy6U8PTO0h0Ws/PdkcOKuXGkx31t/Y32ivFoy7xYPnPt/Z/aNMiHvbO7faQAwuJ/NsG9G1FFRRHCqc73TUsRdKHVuf17BEp526RG6RBZtM3F3V3o0d8/sLmyrNI9tFfksB4qcWiN4P+BRtGr0iacmBfBOvAFSozfUYxjMpx+BYPOpD1pf4fMFoKxxKeJYY31XqZoQLp75RgmWhWYm8URHq4Cjs=\u0026lt;/CipherValue\u0026gt;\      \u0026lt;/CipherData\u0026gt;\    \u0026lt;/EncryptedData\u0026gt;\  \u0026lt;/connectionStrings\u0026gt;
\\

上面的配置適用於Windows IIS。其中,configProtectionProvider鍵值指定了應用所使用的解密類和證書。如果配置未起作用,那麼重新執行上面介紹的Import-PfxCertificate命令。

\\

加密自定義配置部分

\\

使用者不僅可以加密連線串,而且可以加密使用IConfigurationSectionHandler構建的自定義配置部分。要實現該功能,類似於對WebConfigEncrypter.dll的操作,使用者必須將定義使用者配置類的軟體庫拷貝到aspnet_regiis所在的目錄。

\\

首先,要確定在configSections列表中對自定義配置使用了完全限定類名和程式集名。例如:

\\
\  \u0026lt;configSections\u0026gt;\    \u0026lt;section name=\"protectedSettings\" type=\"MyConfigSectionHandler.MyHandler, WebApplication1\" /\u0026gt;\  \u0026lt;/configSections\u0026gt;
\\

這是aspnet_regiis的要求的,無論使用者是否只能提供類名。

\\

然後,使用者需要再次執行加密命令,並將其中的-pef引數替換為自定義部分名稱。 

\\
\aspnet_regiis -pef \"protectedSettings\" \".\" -prov \"Pkcs12Provider\"
\\

Azure App Services中的一些特殊考慮

\\

由於Azure App Service使用當前使用者而非機器儲存並提供證書,因此需要對storeLocation屬性做如下更改: 

\\
\\u0026lt;add name=“Pkcs12Provider” thumbprint=“1234123412341234123412341234123412341234\" type=“WebConfigEncrypter.Pkcs12ProtectedConfigurationProvider, WebConfigEncrypter” storeLocation=“CurrentUser”/\u0026gt;
\\

作者簡介

\\

3b28730168a6e991c1e8ded645fd98d7.jpgJonathan Allen 在90年代後期開始為一家健康診所開發MIS專案,將逐步從Access和Excel遷移成為一個企業解決方案。在為金融行業開發自動交易系統五年後,他成為各種專案的顧問,其中包括機器人倉庫的使用者介面、癌症研究軟體的中間層以及大型房地產保險公司的大資料解決方案。在空閒時間,他喜歡學習有關16世紀武術的東西。

\\

檢視英文原文: Securing web.config with Encryption Certificates on Windows and Azure

相關文章