6

【潛盾機】web.config連線字串加密工具

 2 years ago
source link: https://blog.darkthread.net/blog/web-config-connstr-encryptor-v09-cht/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

【潛盾機】web.config連線字串加密工具

calendar.svg 2010-08-29 04:52 PM comment.svg 35 eye.svg 68,212

ASP.NET 2.0起,web.cofig裡多了connectionStrings區段專門用以儲存資料庫連線字串,同時為避免連線字串中的帳號、密碼等機密資訊曝光,區段內容可以加密方式儲存。例如:

<connectionStrings>
<add name="PlaygroundConnectionString" connectionString="Data Source=(local);Initial Catalog=Playground;Integrated Security=True" providerName="System.Data.SqlClient" />
</connectionStrings>

經加密後會變成:

<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>a44a3giX...略...o+VMsXS8os=</CipherValue>
    </CipherData>
   </EncryptedKey>
  </KeyInfo>
  <CipherData>
<CipherValue>TX5qKv+s...略...3YgrV5wcA==</CipherValue>
  </CipherData>
</EncryptedData>
</connectionStrings>

如此,即便web.config遭竊,拿不到藏在伺服器主機的RSA金鑰,要破解取出帳號密碼資料難如登天。關於加解密web.config區段的做法,微軟MSDN有詳細說明:

但美中不足的是,這些加解密動作目前只能透過aspnet_regiis.exe命令列工具完成,要操作得弄清楚一堆參數。假設今天我們要加密web.config,並部署到三台機器上,全部操作如下:

  1. 用aspnet_regiis -pc "SharedKeys"–exp建立三台機器共用的RSA金鑰容器(Key Container)
  2. 以aspnet_regiis -px "SharedKeys" keys.xml -pri將RSA金鑰容器匯出成XML檔
  3. 將keys.xml複製到三台機器上
  4. 在三台機器上執行aspnet_regiis -pi "SharedKeys" keys.xml滙入RSA金鑰容器
  5. 在三台機器上執行aspnet_regiis -pa "SharedKeys" "NT AUTHORITY\NETWORK SERVICE"授與ASP.NET程式執行權限 (2010-08-30更新: IIS 7.5預設會使用IIS APPPOOL\YourAppPoolName帳號而非NT AUTHORITY\NETWORK SERVICE,詳情可參見保哥的文章,以下應用到授權的地方均比照,不再重複說明。)
  6. 在web.config中加入
    <configProtectedData>
    <providers>
      <add keyContainerName="SharedKey" useMachineContainer="true"
       name="SharedKey" type="System.Configuration.RsaProtectedConfigurationProvider,System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
    </providers>
    </configProtectedData>
  7. 使用aspnet_regiis -pe "connectionStrings" -app "/WebApplication" -prov "SharedKeys"加密連線字串區
  8. 將加密後的web.config部署到三台機器上

以上的步驟挺繁雜的,細節頗多,我一直覺得應該要有輔助工具簡化操作較為人性化,因此我寫了Web Config ConnectionString Ecnryptor!

它是一個小工具程式,說穿了只是提供GUI的方式讓使用者輸入選項,完成原本須透過aspnet_regiis.exe才能達成的web.config加解密及RSA金鑰容器管理功能。

操作介面還蠻直覺的,下拉選單可列出本機上所有的網站應用程式,選擇要處理的web.config,下方視窗就會顯示其內容,按下【編輯】鈕可開啟Notepad進行編輯。若web.config的connectionStrings尚未加密,可按下【加密】鈕對連線字串加密;至於已加密的web.config,【加密】鈕會變成【解密】鈕,也是按一下鈕就可解密,省卻原本複雜的操作。

針對RSA金鑰容器的建立、刪除、匯出、匯入,也一併提供了GUI介面進行管理。

0974-b009-o.gif

另外,順便練習了一下.NET多語系程式開發,程式目前支援英語與正體中文。

以下說明幾種典型應用情境之操作步驟:

  1. 單一網站主機加密(使用預設加密金鑰)
    a) 由下拉選單選取網站應用程式
    b) 按下【加密】鈕
  2. 單一網站主機加密(指定特定金鑰容器)
    a) 由下拉選單選取網站應用程式
    b) 輸入金鑰容器名稱
    c) 按下【加密】鈕
    (web.config中會新增<configProtectedData><providers>並加入以金鑰容器名稱為名的RsaProtectedConfigurationProvider;若該金鑰容器不存在,系統會自動新增,但自動建立的金鑰容器無法匯出給其他機器共用。如針對Web Farm,請參考下一情境。)
    d) 開啟【管理金鑰容器】功能
    e) 輸入金鑰容器名稱,並按下【授權】鈕
  3. 多台網站主機共用指定RSA金鑰容器加密
    a) 啟動【管理金鑰容器】功能
    b) 輸入金鑰容器名稱,按下【建立】鈕
    c) 按【授權】鈕
    c) 按下【匯出】鈕,另存XML檔案
    d) 將XML檔案複製到要部署的網站主機,在該主機執行Web Config ConnectionString Encryptor,使用【管理金鑰容器】功能,輸入金鑰容器名稱,選取XML檔案後按下【匯入】,並執行【授權】(操作完畢請將XML檔案刪除,防止金鑰外洩)
    e) 在下拉選單選取網站應用程式
    f) 輸入金鑰容器名稱
    g) 按下【加密】鈕
    h) 將web.config複製到要部署的網站主機

我將程式及原始碼放到CodePlex中,歡迎大家參考指教!
(聲明: 雖然我認為本工具原理簡單,出錯機率不高,但各位仍請自行衡量風險決定是否使用,在此恕不對它可能造成的任何損失負責。)

CodePlex: Web Config ConnectionString Encryptor

and has 35 comments

Comments

# 2010-09-22 06:36 PM by Jeffrey

to aliku, 以上程式需要管理者權限在本機上執行,我想並不適用於Shared Web Hosting(只能透過FTP或Web UI部署程式的那種虛擬主機)... 除了用aspnet_regiis外,.NET 2.0+支援SectionInformation.ProtectSection()方法對web.config加密,只是承租的虛擬網站多半會調低ASP.NET程式的trust level,所以可能需要在section上加註requirePermission="false"。參考: http://bit.ly/alTTA0

# 2012-03-20 04:38 AM by stn

to # Jeffrey 首先感謝分享,剛好工作上遇到個廠商開發的程式, 在不改連線方式可以簡單加密是真的很有幫助.

但是我遇到個怪問題,下拉選單有部份網站無法看到.

有改授權對象 IIS_WPG ( IIS5,6 ) 也是不行..

有查了一下程式,可能是 string path = String.Format("IIS://{0}/W3SVC", ip);的問題,

因為我有把預設站台拿掉,自己再新增站台.

如果要改成抓iis 上所有網站,不知該如何修改.

抱歉對這塊不熟,尚請高手指導

# 2012-05-04 07:37 AM by 周阿中

To stn: 您是否遇到某些虛擬目錄沒有在這支程式裡的列表出現? 我今天發現問題在哪了,您是否是在站台裡面某個普通目錄按右鍵選內容,再按"建立"的方式來將該目錄變成虛擬目錄? 若是這樣的方式就不會在列表出現喔! 必須手動在站台建立虛擬目錄,(虛擬目錄名稱要與原本目錄名稱相同,這樣才不會同一個目錄有兩個入口),這樣才會出現在這支程式的列表裡面~ 今天也是研究了很久,然後慢慢地將許多虛擬目錄重建...@@

# 2013-03-17 08:41 AM by wong

Firstly, thanks so much for sharing your talents and works. It is a great tool you have created. I'm sorry for not being able to type in Chinese, even though I can read it.

I cannot find the source code of the newer v0.95 in CodePlex.

When I run the v0.90a source on VS2010 on Win7, I have the error of: "Exception has been thrown by the target of an invocation" at the Application.Run(new Form1()); in the Program.cs file. I think I didn't see this error before when I ran it on another PC. Not sure why I encounter this now.

How can I fix this, please?

One suggestion, and I don't know if it's possible to change, is instead of looking for the Web.Config file from the IIS server, can it just browse the Web.Config file from a folder we select instead? This would be much easier for us to use during Dev especially as we do not have to install the Web App to IIS, because we may run it directly within VS (Visual Studio)

Thanks much again.

# 2013-03-17 09:06 AM by Jeffrey

to wong, 感謝您的肯定。 關於"Exception has been thrown by the target of an invocation",建議檢查出錯時的Exception.InnerException,可能會有較明確的錯誤資訊。 v0.95版只多加入當年customError資安漏洞的警示,稍後ASP.NET Team已修復該問題,故0.95版已無價值,原則上這個專案仍以v0.9的Source為準,至於修改成在無IIS模式下瀏覽web.config進行修改,技術上或許可行,但這個工具的目標在簡化IIS設定步驟,也需與實際運作主機加密容器搭配,故預期不會為此改版,但您可試著修改原始程式碼符合您的需求。

# 2013-03-17 02:41 PM by wong

Thanks Jeffrey for your prompt reply.

There is no other information or msg about this Exception. I clicked View Detial link under the Msg box when this occurs, but the detail msg is exactly the same. I ran it as Admin already. I wish I can send you the screen shot, but again the msg is the same: "Exception has been thrown by the target of an invocation".

It happens when the App is being loaded at the line: Application.Run(new Form1());

I cannot do anything about it.

Maybe could you try and see if it works on Win7 and VS2010, please? I tried the EXE on Win XP and it still has the same problem. Thanks.

Oh, I found the way to copy and paste the very detail level as below: -------------------------------------------------------------------------------------

System.Reflection.TargetInvocationException was unhandled Message=Exception has been thrown by the target of an invocation. Source=mscorlib StackTrace: at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner) at System.RuntimeMethodHandle.InvokeMethodFast(Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks) at System.Delegate.DynamicInvokeImpl(Object[] args) at System.Windows.Forms.Control.InvokeMarshaledCallbackDo(ThreadMethodEntry tme) at System.Windows.Forms.Control.InvokeMarshaledCallbackHelper(Object obj) at System.Threading.ExecutionContext.runTryCode(Object userData) at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Windows.Forms.Control.InvokeMarshaledCallback(ThreadMethodEntry tme) at System.Windows.Forms.Control.InvokeMarshaledCallbacks() at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg) at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData) at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context) at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context) at System.Windows.Forms.Application.Run(Form mainForm) at WebConfigEncryptor.Program.Main() in C:\Dev\Encryption\EncryptWebConfigTool4MutliServers_WithSrcFromCodePlex\WebConfigEncryptor_v0.9a\Src\webConfigenc-25482\Program.cs:line 18 at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args) at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() at System.Threading.ThreadHelper.ThreadStart_Context(Object state) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart() InnerException: System.Reflection.TargetInvocationException Message=An exception occurred during the operation, making the result invalid. Check InnerException for exception details. Source=System StackTrace: at System.ComponentModel.AsyncCompletedEventArgs.RaiseExceptionIfNecessary() at System.ComponentModel.RunWorkerCompletedEventArgs.get_Result() at WebConfigEncryptor.Form1.wkrQuery_RunWorkerCompleted(Object sender, RunWorkerCompletedEventArgs e) in C:\Dev\Encryption\EncryptWebConfigTool4MutliServers_WithSrcFromCodePlex\WebConfigEncryptor_v0.9a\Src\webConfigenc-25482\Form1.cs:line 49 at System.ComponentModel.BackgroundWorker.OnRunWorkerCompleted(RunWorkerCompletedEventArgs e) at System.ComponentModel.BackgroundWorker.AsyncOperationCompleted(Object arg) InnerException: System.Runtime.InteropServices.COMException Message=Unknown error (0x80005000) Source=System.DirectoryServices ErrorCode=-2147463168 StackTrace: at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail) at System.DirectoryServices.DirectoryEntry.Bind() at System.DirectoryServices.DirectoryEntry.get_IsContainer() at System.DirectoryServices.DirectoryEntries.ChildEnumerator..ctor(DirectoryEntry container) at System.DirectoryServices.DirectoryEntries.GetEnumerator() at IISDataHelper.exploreTree(DirectoryEntry de, XElement xe, Action`1 cb) in C:\Dev\Encryption\EncryptWebConfigTool4MutliServers_WithSrcFromCodePlex\WebConfigEncryptor_v0.9a\Src\webConfigenc-25482\IISDataHelper.cs:line 30 at IISDataHelper.ReadSettings(String ip, String uid, String pwd, Action`1 progressCallback) in C:\Dev\Encryption\EncryptWebConfigTool4MutliServers_WithSrcFromCodePlex\WebConfigEncryptor_v0.9a\Src\webConfigenc-25482\IISDataHelper.cs:line 20 at WebConfigEncryptor.Form1.wkrQuery_DoWork(Object sender, DoWorkEventArgs e) in C:\Dev\Encryption\EncryptWebConfigTool4MutliServers_WithSrcFromCodePlex\WebConfigEncryptor_v0.9a\Src\webConfigenc-25482\Form1.cs:line 31 at System.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs e) at System.ComponentModel.BackgroundWorker.WorkerThreadStart(Object argument) InnerException:

# 2013-03-17 08:17 PM by Jeffrey

to wong, 感謝提供詳細錯誤資訊,似乎也呼應了早先另一位網友Wang在2013/2/5反應的System.Runtime.InteropServices.COMException (0x80005000)問題。 由錯誤訊息推測問題與IIS ADSI Provider 安裝有關,stackoverflow上有一則相關討論(http://stackoverflow.com/questions/507519/crashing-with-c-sharp-and-directory-services-on-xp),有網友回報在重裝IIS後問題排除,希望這點資訊對你有幫助。

# 2013-03-18 11:15 AM by wong

(I submitted the reply last night and don't see it posted for some reasons. So I try to retype it again.)

Thanks Jeffrey again for the tip. After installing IIS again with more options checked, it works! I checked most of the items under Security and the others under other main branches though. I don't know which ones fixed this issue.

Now when I run it, I have couple questions:

1. What is the Key Container Name that text box that we can leave it empty?

2. Where / how can I set a password when I want to encrypt the ConnectionString section using RSA?

Thanks so much again.

# 2013-03-18 08:18 PM by Jeffrey

to Wong, ASP.NET加密web.config的做法是使用RSA非對稱金鑰,這些加解密金鑰被保存在金鑰容器中,ASP.NET知道如何取出使用,加解密時不需要再額外提供密碼。系統有一個預設的金鑰容器,當工具介面的Key Container Name留白不指定時,就會用預設的金鑰加解密web.config;另外你也可以選擇不要用預設的金鑰,自行建立額外的金鑰容器使用,此時就要填入自訂金鑰容器的名稱。相關細節可參考文中的應用情境說明。

# 2014-08-12 05:35 AM by Gpx1981

你好: 真不好意思翻出這麼舊的文章

目前在匯出金鑰時出現問題 建立金鑰成功,嘗試再次建立也說已存在 但無法匯出跟刪除 希望能指引一條明路QQ

Thanks,

c:\Windows\Microsoft.NET\Framework\v2.0.50727>aspnet_regiis -pc "SharedKeys"–exp 正在建立 RSA 金鑰容器... RSA 金鑰容器已經存在。 失敗!

c:\Windows\Microsoft.NET\Framework\v2.0.50727>aspnet_regiis -px "SharedKeys" keys.xml -pri 正在將 RSA 金鑰匯出至檔案... 找不到 RSA 金鑰容器。 失敗!

c:\Windows\Microsoft.NET\Framework\v2.0.50727>aspnet_regiis -pz "SharedKeys" 正在刪除 RSA 金鑰容器... 找不到 RSA 金鑰容器。 失敗!

Post a comment

Comment
Name Captcha 55 - 43 =

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK