在將ASP.NET項目部署到服務器上時,內網環境下Web.Config每每是直接複製過去。對於外網環境,則須要對Web.Config文件進行加密。web
.NET環境下一共提供了2種方式的加密功能,分別是DpapiProtectedConfigurationProvider和RsaProtectedConfigurationProvider提供程序。sql
前者在本機加密Web.Config後,只能在本機進行解密,若是須要將Config文件複製到外部主機,則沒法進行解密。後者在本機加密Config文件後,能夠處處密鑰容器,當把Config文件複製到外部主機後,可對先前導出的文件進行導入功能,導入後既可自動解密。c#
因爲常常須要複製Config文件到外部主機,所以Rsa保護程序更加適用於實際業務場景,本文將詳細介紹RsaProtectedConfigurationProvider程序的使用步驟。api
1. 使用RsaProvider提供程序,須要首先進入.NET Framework運行環境,能夠配置環境變量或使用cd指令。服務器
cd C:\Windows\Microsoft.NET\Framework\v2.0.50727session
2. 接着即可以使用aspnet_regiis.exe建立一個Rsa密鑰容器。密鑰容器分用戶級別和計算機級別兩種狀況,因爲使用用戶級別密鑰沒什麼益處,通常使用計算機級別既可。asp.net
aspnet_regiis -pc "MyKeys" -expide
3. 建立密鑰容器後,還須要設置密鑰容器的訪問權限,下面的命令授予NETWORK SERVICE 賬戶對計算機級別的 「MyKeys」 RSA 密鑰容器的訪問權限。msdn上有一個aspx程序會展現你的asp.net程序的用戶標誌,不過本人實際執行pa指令後會報錯。網站
aspnet_regiis -pa "MyKeys" "NT AUTHORITY\NETWORK SERVICE"加密
4. 在Web.Config文件中加上以下配置節點,MyProvider爲你的保護程序名稱,可隨意指定。keyContainerName爲前面設置的密鑰容器名稱,useMachineContainer爲true表示使用計算機級別密鑰,爲false表示使用使用用戶級密鑰。
這段配置節不要像msdn那樣直接放在configure配置節點下面,這樣會報錯,建議放在你須要加密節點的後面。
<configProtectedData>
<providers>
<add name="MyProvider"
type="System.Configuration.RsaProtectedConfigurationProvider, System.Configuration, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a,
processorArchitecture=MSIL"
keyContainerName="MyKeys"
useMachineContainer="true" />
</providers>
</configProtectedData>
5 .下面的指令將對指定路徑下的config文件節點進行加密,若是配置文件中還有session的sql鏈接字符串,也能夠對sessionState節點進行加密。
aspnet_regiis -pef "connectionStrings" "D:\WebApp" -prov "MyProvider"
aspnet_regiis -pef "system.web/sessionState" "D:\WebApp" -prov "MyProvider"
加密後的connectionStrings節點以下所示,此時仍可訪問ASP.NET應用程序。
<connectionStrings configProtectionProvider="MyProvider"> <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns="http://www.w3.org/2001/04/xmlenc#"> <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" /> <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"> <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#"> <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" /> <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"> <KeyName>Rsa Key</KeyName> </KeyInfo> <CipherData> <CipherValue>X3XoBfbo/h9QUeVUV8A1EGMM0NQuBnhfuC/iV1e7CCmGaiRt9ogmICenTK8VAmGfhufPzWFu5UUHSiO/6BIvYPEO5WoWlj3h5/sUQmRj6NsAJOnrnYHEjta4oQb4XajxazWcf3HUeWR0mG4wDCiUfTZaRIRmXkGgfbxewpsKJ5k=</CipherValue> </CipherData> </EncryptedKey> </KeyInfo> <CipherData> <CipherValue>suqFgGjGFaon62YNI2VM5SQymcf4yyAku9fWQuvgClj1bfqixK9kIs9IE0I0m2u4gLbF+y0xPharfcOFJpXHDwHoaCrNQsxsutqiXquX67bYcJeYaMz5ja9ebqAtQvKIiZ/kHGvFIPXSCg5HiW/GGQwaf3FESVEsOaSAJZ3JJk9MlkkwDd6LepgtcCVjLnEK0lOeEFznrngizFFZWAsYjh5UCF5lNxNxf/IBwtznsfiFi2tV1F4sx9HkJEEryf5MEtu1RAA/wqarMvn7dlXhpGconpNPXA1IGlTmaZ/S1bR/FsO39skgHrs+OHsDMbJrI5ZO4TXXbK/DD86GPzu9JXrVKNVImzzW0V8aMc2HcVNClPsMwwgGaH6PNhE0xkjV6YH77XcLdVsKibvnwMlO/4kjGKoNXaSkFBoAEgprzi8=</CipherValue> </CipherData> </EncryptedData> </connectionStrings>
若是須要解密,能夠執行下面這條指令aspnet_regiis -pdf "connectionStrings" "D:\WebApp"
<connectionStrings> <add name="DefaultConnection" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\aspnet-WebApp-20170622060005.mdf;Initial Catalog=aspnet-WebApp-20170622060005;Integrated Security=True" providerName="System.Data.SqlClient" /> </connectionStrings>
6. 導出密鑰容器,密鑰信息將被存儲在導出的xml文件中,pri表示將公鑰和私鑰一塊兒導出。
aspnet_regiis -px "MyKeys" "D:/MyKeys.xml" -pri
7. 有了這個xml文件,就至關於有了密鑰容器,導出密鑰容器後能夠對密鑰容器進行刪除,刪除指令以下。
aspnet_regiis -pz "MyKeys"
8. 刪除密鑰容器後,若是前面你沒有對Config文件進行解密,那麼運行ASP.NET程序將會直接報錯。
在本人實際操做中發現,若是對正在運行的ASP.NET應用程序的Web.Config文件進行加密,加密後當即刪除密鑰,此時點擊運行(不調試)仍可正常訪問。這代表Rsa解密操做在內存中執行,只有從新生成解決方案或調試(會執行生成操做)後,訪問纔會報錯。
9. 如今能夠將加密後的config文件和導出的MyKeys.xml一塊兒複製到服務器上,此時運行網站將會直接報錯,需執行下面的導入指令。
aspnet_regiis -pi "MyKeys" "D:/MyKeys.xml"
導入後,在本機訪問ASP.NET網站會發現仍然報錯,提示沒法open Provider。這個坑最終在網上找到解決方法,以下面指令所示,須要爲應用程序池設置對密鑰容器的訪問權限。
aspnet_regiis -pa "MyKeys" "IIS APPPOOL\MyWeb" -full
自此整個流程已結束,能夠將上面這些指令封裝成2個批處理程序,一個是密鑰製做bat,一個是導入bat,以下所示。
@echo on cd C:\Windows\Microsoft.NET\Framework\v2.0.50727 ::設置config地址,config文件要在E:\test下面 set configAddress="E:\test" ::建立RSA密鑰容器 aspnet_regiis -pc "MyKeys" -exp ::設置密鑰容器訪問權限 aspnet_regiis -pa "MyKeys" "NT AUTHORITY\NETWORK SERVICE" ::加密 aspnet_regiis -pef "connectionStrings" "D:\WebApp" -prov "MyProvider" aspnet_regiis -pef "system.web/sessionState" "D:\WebApp" -prov "MyProvider" ::導出 aspnet_regiis -px "MyKeys" "D:/MyKeys.xml" -pri ::刪除密鑰容器 aspnet_regiis -pz "MyKeys" pause
@echo on cd C:\Windows\Microsoft.NET\Framework\v2.0.50727 ::刪除舊的密鑰容器 aspnet_regiis -pz "MyKeys" ::導入新的密鑰容器 aspnet_regiis -pi "MyKeys" "D:/MyKeys.xml" ::設置應用程序池的訪問權限 aspnet_regiis -pa "MyKeys" "IIS APPPOOL\MyWeb" -full pause
在寫完這2個bat後,我想起前面的解密指令aspnet_regiis -pdf "connectionStrings" "D:\WebApp",它只須要提供節點名稱和路徑。也就是說,若是攻擊者可以在被攻擊的服務器上執行cmd指令,那麼他就能夠對config進行解密。這個問題若有前輩有更好的解決方式,歡迎您指導留言。
若是當初微軟編寫這個指令解析方法時,加上一個key的參數。那麼即便攻擊者可以執行cmd指令,因爲不知道key的名稱,因此仍然沒法對config進行解密。
聲明:本文原創發表於博客園,做者爲方小白 ,若有錯誤歡迎指出。本文未經做者許可不準轉載,不然視爲侵權。