how to encrypt connection string to avoid password exposure
加密connection string 避免暴露密碼
前言
承上一篇,提交 full code 時負責的同事不作為,現在結果出來了。
很多很多紅字,一般4-5級的都會紅色 highlight 來強調,原來系統有很多hard code的password
沒法了,20年的歷史,也沒法追蹤,太多經手人,總有質素參差的時候。
故事開始
負責fix的同事說沒有辦法,不懂處理。所以這項工作向上提升到了海豚的層次。
很麻煩啊,廢了豚2小時。 Microsoft 的文件就是差,簡單地讓人在VS點一下不就好,寫了幾千字的說明文件只為好看。
已經跟隨一步一步做,結果就是不行。
幸好最後找到一篇好文章,按照教學,終於完成了對 connectionStrings 加密,
做好了,發還給負責的同事,你按照接下來的教學繼續解密的部份吧,豚要趕著處理其它事情。
豚沒有深入細情,不過簡單來說,就是避免 web.config的connectionString 以plain text 形式寫下
Database的各項登入資訊 (destination IP, port, databaseServerName, databaseName, userName, userPwd)
<connectionStrings>
<add name="PIMSEntities" connectionString="metadata=res://*/ModelFile.csdl|res://*/ModelFile.ssdl|res://*/ModelFile.msl;provider=IBM.Data.DB2;provider connection string="Database=databaseServerName;User ID=userName;Password=userPwd;CurrentSchema=databaseName;Server=192.168.0.1:50004;Max Pool Size=100;Min Pool Size=50;"" providerName="System.Data.EntityClient" />
</connectionStrings>
這個設計的原意相信是各人只知道一部份的秘密
Developer 掌管 source
DBA 掌管 Database的各項登入資訊
Encrypt的人 掌管 RSA key
PC Admin 的人 掌管 Production(Windows) Server的login
Deploy 的人設定IIS掛上RSA key
System User admin 掌握 System 的user login
當有人駭進application server時,看到的只是一堆亂碼,不知道 Database的各項登入資訊
便無法入侵db 改資料
Developer 掌管 source,不知道DB登入資訊,即是沒有Production Data 的存取權
source在離開developer手上時已compile,以下各人手上拿的都是 compile 後的source,沒法對source動手腳,不可修改系統
DBA 雖然管Database的各項登入資訊,但沒有 producation user login,也沒法經系統做什麼。
而敏感的個人資料都經由db 於column / row / table 等不同程度的加密,或經application自行
加密。所以也看不到重要資訊,如果自行修改沒有被加密的資料,被發現也只是時間問題。
Release Manager 與DBA同理,而生成完的RSA KEY
令豚想起一部抽中你是幸運兒便要去死的作品
以下用到的script 都放在One drive
.net4 encrypt webConfig connectionStrings有需要自行下載玩
command 指令 v4.0.30319
加密需要的工具在
C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe
海豚一找就有了,放在.net framework 底下的,估是跟VS installer 安裝
本來就有在開發的所以有安裝 .net framework ,沒有的先自行安裝。在此不列出安裝步驟,不想令本文太長。
如果只有舊版本也是可以的,不過舊版本的步驟好像有點不同,往再下一個段落。
簡單來說步驟如下︰
Generate / Create RSA KEY
Export RSA Key
Publish your VS application
Add RsaProtectedConfigurationProvider with Key name in your web.config file
加密 connectionStrings
加密 appSettings
Generate / Create 生成 RSA KEY
cd C:\Windows\Microsoft.NET\Framework\v4.0.30319\
rem 3. generate key named SampleKeys
C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe -pc "SampleKeys" –exp
rem 4. grant access to Network Service, type & run command
C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe -pa "NetFrameworkConfigurationKey" "NT AUTHORITY\NETWORK SERVICE"
rem 5. Similarly-
C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe -pa "SampleKeys" "NT AUTHORITY\NETWORK SERVICE"
Export 匯出 RSA Key
rem 6. Export the Container Key to xml - it will generated in C:\Keys folder you created.
aspnet_regiis -px SampleKeys C:\SampleKeys.xml -pri
匯出的檔案是
<RSAKeyValue><Modulus></Modulus>
...
</RSAKeyValue>
Publish 發佈 your VS application
rem 7. publish your application, edit the published Web.Config
rem for me is C:\Users\DolphinOtaku\Documents\ImageSharing\PIMS.WcfService\bin\PRD\publish
Add RsaProtectedConfigurationProvider with Key name in your web.config file
rem 8. Write below code in Web.Config of application just after closing of <configSections>,
rem which is a CustomProvider for encryption
修改你發佈的web.config,例子如下
<configuration>
<configSections>
//Your existing code here
</configSections>
<configProtectedData defaultProvider="MyProvider">
<providers>
<add name="MyProvider"
type="System.Configuration.RsaProtectedConfigurationProvider,
System.Configuration, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a,
processorArchitecture=MSIL"
keyContainerName="SampleKeys"
useMachineContainer="true"/>
</providers>
</configProtectedData>
</configuration>
加密 connectionStrings
rem 9. Encrypt appSettings & connectionStrings using custom provider
aspnet_regiis -pef "connectionStrings" "C:/inetpub/wwwroot/PIMS_DEV/ImageSharing" -prov "MyProvider"
加密 appStrings
aspnet_regiis -pef "appSettings" "C:/inetpub/wwwroot/PIMS_DEV/ImageSharing" -prov "MyProvider"
加密後的結果就變成亂數
在伺服器匯入RSA Key
使伺服器IIS能在運行API/website/application 時解密
豚只嘗試了加密,解密沒有試,照下文做應該沒有問題吧。
rem 10. import key steps, please read https://www.codeproject.com/Tips/1041938/Encrypting-Applications-web-config-Using-NET-Frame
舊版本 v2.0.50727\aspnet_regiis.exe
使用的舊版本 是
C:\Windows\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis.exe
以上 生成Key,修改web.config……的步驟還是要進行,不同的只有v2 和v4的指令
同事 給豚的檔案如下
WebConfig_Encrypt.bat
WebConfig_Dencrypt.bat
放在publish folder 底下,結構如下
publish\WebService.svc
publish\web.config
publish\WebConfig_Encrypt.bat
publish\WebConfig_Dencrypt.bat
publish\bin
右按以管理員身份執行WebConfig_Encrypt.bat 變可將web.config加密
加密後想還原執行WebConfig_Dencrypt.bat
當中遇到的困難
必須透過VS publish web service 後的這個web.config 才可以加 configProtectedData
如果在source code 的web.config 預早加入,VS rebuild / publish時會視 configProtectedData 無法辨認,自動幫你刪除。這設計真的有夠麻煩。
即是說要Encrypt,每次deploy便多一個步驟。
不可在 inetpub/wwwroot 進行加密
豚試過了
aspnet_regiis -pef "connectionStrings" "C:/inetpub/wwwroot/systemSource/webAPI" -prov "MyProvider"
永遠失敗的,搬位置後立即成功
aspnet_regiis -pef "connectionStrings" "C:\Users\keithpoon\Documents\systemSource\webAPI" -prov "MyProvider"
後來發現不關路徑事,是斜錯了,要用\才可
並且 Run as Admin...
之前只是權限不夠
Reference
Encrypting Applications web.config Using .NET Framework Utility
https://www.codeproject.com/Tips/1041938/Encrypting-Applications-web-config-Using-NET-Frame
Encrypting and Decrypting Configuration Sections
https://learn.microsoft.com/en-us/previous-versions/aspnet/zhhddkxy(v=vs.100)
Importing and Exporting Protected Configuration RSA Key Containers
https://learn.microsoft.com/en-us/previous-versions/aspnet/yxw286t2(v=vs.100)
No comments:
Post a Comment