2022年4月13日 星期三

[研究][ASP.NET]Fortify SCA報告Password Management: Password in Configuration File 問題,與Web.Config資料庫連線字串加密後拿去別台可用性測試

[研究][ASP.NET]Fortify SCA報告Password Management: Password in Configuration File 問題,與Web.Config資料庫連線字串加密後拿去別台可用性測試

2022-04-13

環境:Visual Studio 2022 + ASP.NET + WebForm + Web Application + C#

Micro Focus Fortify SCA ( Static Code Analyzer ) 原始碼掃描工具 ( 源碼掃描) 經常會報告 Web.config 中資料庫連線字串有 Password Management: Password in Configuration File 問題;這是因為連線字串中有一個關鍵字 Password。

註:另外,Web.Config 中 key name 若包含 Password 關鍵字就會被認為有問題,Pwd 則可以;而 key value 若包含 Password 或 Pwd 都會被認為有問題。

解決方法:簡單的說,把資料庫連線字串加密就解決了。

但實務層面上,事情沒那麼簡單。因為加密連線金鑰是儲存於本機。所以加密後,不管是 Source Code 或發佈 (deploy) 後編譯過的程式碼,拿到別台可能無法使用,本篇來實際測試一下可行性。

Default.aspx

<%@ Page Language="C#" AutoEventWireup="true" 
    CodeBehind="Default.aspx.cs" Inherits="WebApplication1.Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:SqlDataSource ID="SqlDataSource1" runat="server" 
                ConnectionString="<%$ ConnectionStrings:TestDBConnectionString %>" 
                SelectCommand="SELECT * FROM [Table1]"></asp:SqlDataSource>
            <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" 
                DataKeyNames="SN" DataSourceID="SqlDataSource1">
                <Columns>
                    <asp:BoundField DataField="SN" HeaderText="SN" 
                        InsertVisible="False" ReadOnly="True" SortExpression="SN" />
                    <asp:BoundField DataField="CName" HeaderText="CName" SortExpression="CName" />
                </Columns>
            </asp:GridView>
            <br />
            <asp:SqlDataSource ID="SqlDataSource2" runat="server" 
                ConnectionString="<%$ ConnectionStrings:TestDBConnectionString2 %>" 
                SelectCommand="SELECT * FROM [Table1]"></asp:SqlDataSource>
            <asp:GridView ID="GridView2" runat="server" AutoGenerateColumns="False" 
                DataKeyNames="SN" DataSourceID="SqlDataSource2">
                <Columns>
                    <asp:BoundField DataField="SN" HeaderText="SN" 
                        InsertVisible="False" ReadOnly="True" SortExpression="SN" />
                    <asp:BoundField DataField="CName" HeaderText="CName" SortExpression="CName" />
                </Columns>
            </asp:GridView>
        </div>
    </form>
</body>
</html>


Web.Config 原來內容


<?xml version="1.0" encoding="utf-8"?>
<!--
  如需如何設定 ASP.NET 應用程式的詳細資訊,請前往
  https://go.microsoft.com/fwlink/?LinkId=169433
  -->
<configuration>
  <connectionStrings>
    <add name="TestDBConnectionString" connectionString="Data Source=.;Initial Catalog=TestDB;Persist Security Info=True;User ID=testuser;Password=P@ssw0rd"
      providerName="System.Data.SqlClient" />
    <add name="TestDBConnectionString2" connectionString="Data Source=10.3.99.210;Initial Catalog=TestDB;Persist Security Info=True;User ID=testuser;Password=P@ssw0rd"
      providerName="System.Data.SqlClient" />
  </connectionStrings>
  <system.web>
    <compilation debug="true" targetFramework="4.8" />
    <httpRuntime targetFramework="4.8" />
  </system.web>
  <system.codedom>
    <compilers>
      <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701" />
      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+" />
    </compilers>
  </system.codedom>
</configuration>

測試,確認可以存取某遠端 SQL Server 上某資料庫內容


********************************************************************************
加密

cd   C:\Windows\Microsoft.NET\Framework64\v4.0.30319
aspnet_regiis.exe   -pef   資料庫連線字串區段名稱   "原始碼Web.Config所在目錄"


C:\>cd   C:\Windows\Microsoft.NET\Framework64\v4.0.30319
C:\Windows\Microsoft.NET\Framework64\v4.0.30319>aspnet_regiis.exe -pef connectionStrings C:\CodeTemp\WebApplication1\WebApplication1 Microsoft (R) ASP.NET RegIIS 版本 4.0.30319.0 在本機電腦上安裝及解除安裝 ASP.NET 的管理公用程式。 Copyright (C) Microsoft Corporation. 著作權所有,並保留一切權利。 正在加密組態區段... 成功! C:\Windows\Microsoft.NET\Framework64\v4.0.30319>


Web.Config 中,資料庫連線字串區段 (connectionStrings),加密後的結果

<?xml version="1.0" encoding="utf-8"?>
<!--
  如需如何設定 ASP.NET 應用程式的詳細資訊,請前往
  https://go.microsoft.com/fwlink/?LinkId=169433
  -->
<configuration>
	<connectionStrings configProtectionProvider="RsaProtectedConfigurationProvider">
  <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#aes256-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-oaep-mgf1p" />
     <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
      <KeyName>Rsa Key</KeyName>
     </KeyInfo>
     <CipherData>
      <CipherValue>I1Ayu5jAvHovXMX5Wa215a0tIF29gyCNPEbduAbV7rh5sqYKl7Xtcd8+64UcWcFVPljawxQSYybgQjrsbHGBZsuT7ED7qIymaKSmCqa89wgQkLP+1sVRaenHbGek6Y1M/YZpEQrACZagPHo72MJHbpcvOsvthYCU5MOPUfJtSxKDy+ZpTZLi2qzdCLmCloOJDmfwMD69jmrfLYQ/Jd+2fSFdbBZkUxO2gLzHKJDdCpwt9U09tjQ0kEVS0mKR/IJ5bgOUeZOACiYa5Xe22uMqK+zBKRMe5dHswdScl+GWN3bkVpR1TSo/o/45lFwClfGuOsbn0TVl3/iBmZSeI2XGuQ==</CipherValue>
     </CipherData>
    </EncryptedKey>
   </KeyInfo>
   <CipherData>
    <CipherValue>cXMmlu5qn+CNcriGYeorDuISOkNqQL3La6HaFzfKUK9ppSxsZs6W4jzk5QrTOOzLNyhgCeriqP+9h5TAy3wGsv+whnfri6UAJ8+49GIdI5sKB47s5GKf10bdytAJQQCDi5fJznWgWGxPLVxKDR/qtNbFDaoAMedGkZhA6fZVxiB0R06nZImibFGpvXblFdYPnAvc4diJbF+rURC5IBwSDBYNlpsEb4/wnrZCm3pasqZq7QJTQF08DwCarHH6RreoUu5MlrY9Dg6h/Ec7R+MGpAvg8Su+MPuPYukzjVlvY2MD9XwTux8vRZVFo9YdgaUtZ4MHXYos5lE2WjOQf+kEm/xoE7zhtvA0fYlsaNs0b1M=</CipherValue>
   </CipherData>
  </EncryptedData>
 </connectionStrings>
	<system.web>
		<compilation debug="true" targetFramework="4.8" />
		<httpRuntime targetFramework="4.8" />
	</system.web>
	<system.codedom>
		<compilers>
			<compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701" />
			<compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+" />
		</compilers>
	</system.codedom>
</configuration>

測試,加密後依然可以正常執行

********************************************************************************

解密

供參考,為了後面的測試,請勿現在就解密。

cd   C:\Windows\Microsoft.NET\Framework64\v4.0.30319
aspnet_regiis.exe   -pdf   資料庫連線字串區段名稱   "原始碼Web.Config所在目錄"

例如:

cd   C:\Windows\Microsoft.NET\Framework64\v4.0.30319

aspnet_regiis.exe   -pdf   connectionStrings   C:\CodeTemp\WebApplication1\WebApplication1

********************************************************************************

把整個原始程式碼方案拷貝到另一台電腦測試

'/' 應用程式中發生伺服器錯誤。

組態錯誤

描述: 處理服務此要求所需的組態檔時發生錯誤。請檢視下列的特定錯誤詳細資訊,並適當修改您的組態檔。

剖析器錯誤訊息: 無法使用提供者 'RsaProtectedConfigurationProvider' 解密。來自這個提供者的錯誤訊息為: 當解碼 OAEP 填補時發生錯誤。

原始程式錯誤:

行 6:  <configuration>
行 7:  	<connectionStrings configProtectionProvider="RsaProtectedConfigurationProvider">
行 8:    <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
行 9:     xmlns="http://www.w3.org/2001/04/xmlenc#">
行 10:    <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" />

原始程式檔: C:\CodeTemp\WebApplication1\WebApplication1\web.config    行: 8             

********************************************************************************
結論

* 要做資料庫連線加密,請到 Web Server 主機上去做。 如果 Web Server 有分開發機、測試機、正式機,請把未加密的 Source Code 拿去該機器,改好資料庫連線相關資訊 (IP、帳號、密碼),然後再加密。

* 上傳 Git Server 或 SVN Server 的 Source Code,Web.Config請勿把資料庫連線加密;如果是多人開發,別人下載後無法使用;另外自己的開發機若哪天 Windows 損毀要重新安裝,或硬體故障,儲存於本機的加密金鑰就沒了。

* 對於Fortify SCA報告Password Management: Password in Configuration File 問題,這不能算是單純 Source Code 問題;若單純從 Source Code角度看,可以算誤判,於分析總結報告說明  ( 就看花錢的業主 or 長官能否接受);或者掃描前把連線字串註解掉;或者加密 ( 未加密原始 Web.Config 要留好備份 )。

* 如果未加密原始 Web.Config 不見了,可以把加密過 Web.Config 中 <connectionStrings> ...</connectionStrings>區段註解或砍了,利用 SqlDataSource 手動重新建立一個 ( 前提是要知道原來所設定要連線的資料庫主機 IP、資料庫名稱、帳號、密碼 )。

********************************************************************************

附錄:aspnet_regiis.exe 參數

cd   C:\Windows\Microsoft.NET\Framework64\v4.0.30319

aspnet_regiis.exe   /?

C:\Windows\Microsoft.NET\Framework64\v4.0.30319>aspnet_regiis.exe /?
Microsoft (R) ASP.NET RegIIS 版本 4.0.30319.0
在本機電腦上安裝及解除安裝 ASP.NET 的管理公用程式。
Copyright (C) Microsoft Corporation.  著作權所有,並保留一切權利。


                                                   -- ASP.NET 註冊選項 --

-i                            安裝這個版本的 ASP.NET,並且將位於根層級的 IIS 組態更新為使用這個版本的 ASP.NET。

-ir                           安裝這個版本的 ASP.NET,僅註冊。不將任何 Web 應用程式更新為使用這個版本。

-iru                          安裝這個版本的 ASP.NET。如果有任何使用 ASP.NET 的現有應用程式,它不會將 IIS 組態變更為使用這個版本。

-enable                       當 -enable 以 -i、-ir 或 -r 指定時,ASP.NET 也會在 IIS 安全性主控台 (IIS 6.0 或以後) 中啟用。

-disable                      當 -disable 以 -i、-ir 或 -r 指定時,ASP.NET 也會在 IIS 安全性主控台 (IIS 6.0 或以後) 中停用。

-s <path>                     在指定的路徑以遞迴方式安裝這個版本的 Scriptmap。
                              例如 aspnet_regiis.exe -s W3SVC/1/ROOT/SampleApp1

-sn <path>                    在指定的路徑以非遞迴方式安裝這個版本的 Scriptmap。

-r                            安裝這個版本的 ASP.NET,並且更新位於 IIS Metabase 根目錄的 Scriptmap 以及根目錄下的所有
                              Scriptmap。不論其原先版本為何,都會變更為這個版本。

-u                            解除安裝這個版本的 ASP.NET。現有版本的 Scriptmap 會重新對應到電腦上所安裝其他 ASP.NET 版本中最高的版本。

-ua                           解除安裝電腦上所有版本的 ASP.NET。

-k <path>                     從指定的路徑以遞迴方式移除任何 ASP.NET 版本的 Scriptmap (Windows Vista (含) 以上版本不支援)。
                              例如 aspnet_regiis.exe -k W3SVC/1/ROOT/SampleApp1

-kn <path>                    從指定的路徑以非遞迴方式移除任何 ASP.NET 版本的 Scriptmap (Windows Vista (含) 以上版本不支援)。

-lv                           列出電腦上安裝的所有 ASP.NET 版本,以及狀態和安裝路徑。

-lk                           列出 ASP.NET 由指令碼對應的所有 IIS Metabase 索引鍵的所有路徑,並列出其版本。從父索引鍵繼承 ASP.NET Scriptmap 的索引鍵將不會顯示出來
                              (Windows Vista (含) 以上版本不支援)。

-c                            將這個版本的用戶端指令碼安裝到每個 IIS 站台目錄的 aspnet_client 子目錄。

-e                            從每個 IIS 站台目錄的 aspnet_client 子目錄移除這個版本的用戶端指令碼。

-ea                           從每個 IIS 站台目錄的 aspnet_client 子目錄移除所有版本的用戶端指令碼。

-ga <user>                    針對 ASP.NET 所使用的 IIS Metabase 和其他目錄,授與指定的使用者或群組存取權限。



                                                      -- 組態加密選項 --

-pe 區段                        加密組態區段。選擇性引數:
                              [-prov provider] 使用這個提供者進行加密。
                              [-app virtual-path] 在這個虛擬路徑進行加密。虛擬路徑必須以正斜線開頭,如果以 '/' 開頭,則是指網站的根目錄。如果沒有指定 -app,就會對根
                              web.config 進行加密。
                              [-site site-name-or-ID] -app 參數中指定之虛擬路徑的網站。如果沒有指定,將使用預設網站。
                              [-location sub-path] 位置子路徑。
                              [-pkm] 加密/解密 machine.config 而非 web.config。

-pd 區段                        解密組態區段。選擇性引數:
                              [-app virtual-path] 在這個虛擬路徑進行解密。虛擬路徑必須以正斜線開頭,如果以 '/' 開頭,則是指網站的根目錄。如果沒有指定 -app,就會對根
                              web.config 進行解密。
                              [-site site-name-or-ID] -app 參數中指定之虛擬路徑的網站。如果沒有指定,將使用預設網站。
                              [-location sub-path] 位置子路徑。
                              [-pkm] 加密/解密 machine.config 而非 web.config。

-pef 區段 web-app-physical-dir  加密組態區段。選擇性引數:
                              [-prov provider] 使用這個提供者進行加密。

-pdf 區段 web-app-physical-dir  解密組態區段。

-pc 容器                        在 ContainerName 中建立 RSA 金鑰組。選擇性引數:
                              [-size key-size] 金鑰大小。預設為 1024。
                              [-pku] 使用者容器而非機器容器。
                              [-exp] 讓私密金鑰為可匯出狀態。
                              [-csp provider] 要使用的 Csp 提供者。

-pz 容器                        刪除 ContainerName。選擇性引數:
                              [-pku] 使用者容器而非機器容器。

-pi 容器檔案                      由 Xml 檔案匯入 RSA 金鑰組。選擇性引數:
                              [-pku] 使用者容器而非機器容器。
                              [-exp] 建立可匯出的金鑰。
                              [-csp provider] 要使用的 Csp 提供者。

-px 容器檔案                      將 RSA 金鑰組匯出至 Xml 檔案。選擇性引數:
                              [-pku] 使用者容器而非機器容器。
                              [-pri] 包含私密金鑰。
                              [-csp provider] 要使用的 Csp 提供者。

-pa 容器帳戶                      為容器加入帳戶存取權限。引數:
                              [-pku] 使用者容器而非機器容器。
                              [-csp provider] 要使用的 Csp 提供者。
                              [-full] 加入完整存取權限 (預設為讀取權限)。

-pr 容器帳戶                      移除容器的帳戶存取權限。引數:
                              [-pku] 使用者容器而非機器容器。
                              [-csp provider] 要使用的 Csp 提供者。



                                                     -- 組態遠端存取選項 --

-config+                      啟用組態遠端存取。

-config-                      停用組態遠端存取。


C:\Windows\Microsoft.NET\Framework64\v4.0.30319>

(完)

相關

[研究][ASP.NET]Fortify SCA報告Password Management: Password in Configuration File 問題,與Web.Config資料庫連線字串加密後拿去別台可用性測試https://shaurong.blogspot.com/2022/04/aspnetfortify-scapassword-management.html

[研究] [ASP.NET] Web.Config 連線字串加密、解密方法
http://shaurong.blogspot.com/2017/09/aspnet-webconfig.html

[研究][ASP.NET] Fortify SCA 報告 Web.Config 資料庫連線字串設定有 Insecure Transport: Database 問題
http://shaurong.blogspot.com/2018/12/fortify-sca-webconfig.html

保護連接字串和其他設定資訊 (c # ) | Microsoft Docs
https://docs.microsoft.com/zh-tw/aspnet/web-forms/overview/data-access/advanced-data-access-scenarios/protecting-connection-strings-and-other-configuration-information-cs

[研究][Fortify SCA]原始碼變數最好不要包含的字串

[研究]Fortify SCA對Web.Config中 Password Management: Password in Configuration File 的關鍵字認定

[研究][ASP.NET] Fortify SCA 報告 Web.Config 中 add key 有 Password Management Password in Configuration 問題

[研究][ASP.NET]Fortify SCA 報告Password Management: Empty Password 和 Hardcoded Password

沒有留言:

張貼留言