搜尋此網誌

2024年5月7日 星期二

aspnet_regiis.exe 與 webconfig 加密

緣起:


    今天無聊在隨意亂看我們公司建立站台的程式碼時,發現一個有趣的東西,那部份的程式碼有用 #region Config加密 包起來,然後還有用 C# 的 Process 類別來執行一個叫 aspnet_regiis.exe 的程式碼,所以就好奇去查,發現,原來我們的 webconfig 就是用這個東西來加密的。

    想自己動手操作一次並記錄。參考文章


建立金鑰容器:


    我一開始是去確定我電腦上有沒有 C:\Windows\Microsoft.NET\Framework\v4.0.30319 這資料夾,發現有,所以再來就照著下指令

C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe -pc "birdshiutest" -exp

    -pc "金鑰名稱",-exp 代表設定金鑰允許匯出


    這就讓我好奇,能不能用 aspnet_regiis.exe 來條列有哪些 container,我稍微找了一會後,發現好像不行,但在這篇文章看到,可以到 %ProgramData%\Microsoft\Crypto\RSA\MachineKeys 這邊去找。我到那個資料夾後,看到一些以 guid 命名的檔案,它們不是文字檔,所以不能直接用文字編輯器讀


    我猜,最下面那個就是我剛剛新增的 "birdshiutest" 金鑰 Container。

    

對 web.config 加密:


    再來要試著對 webconfig 加密,我選了之前建的 ASP WebForm 專案來當白老鼠 (就那個WebSite1),為了避免弄爆 webconfig 後救不回專案,所以我先對它做備份。

    開始加密,首先,要編輯 web.config,在 <configuration> 節點加入

<configProtectedData defaultProvider="TheKeyProtectedProvider">
    <providers>
      <add name="TheKeyProtectedProvider"
      type="System.Configuration.RsaProtectedConfigurationProvider, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
      keyContainerName="birdshiutest"
      useMachineContainer="true" />
    </providers>
  </configProtectedData>

    再來,要加密 connectionStrings 的區段。我在觀察完文章中指令的格式後,判斷是

aspnet_regiis.exe -pef "{webconfig要加密的區段}" "{webconfig所在資料夾路徑}" -prov "{webconfig裡的protectedprovider名字}"

    我自己下的指令,格式是長這樣

C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe -pef "connectionStrings" "." -prov "TheKeyProtectedProvider"

    然後這是下完指令的回應


    這時再去看 webconfig,哇 ~~ connectionStrings 區段真的有被加密了


    它原本是長這樣的


    從公司的程式碼中,我發現,你是可以對同支 webconfig 多次呼叫 
aspnet_regiis.exe 來加密它上面的各個區段,還發現,對於 {webconfig要加密的區段} 這參數,它是以 <configuration> 為 root,然後像 unix 系統的路徑一樣來指定 <configuration> 內的 node。

    比如說,如果你想加密 configuration > system.web > sessionState,指令可以下



解密:


    解密的話,指令格式是這樣 (pdf XD)。我這時才發覺,pef 的 e 是 encrypt,而 pdf 的 d 是 decrypt
aspnet_regiis.exe -pdf "{要解密的webconfig區段}" "{webconfig所在資料夾路徑}"

    我指令實際是這樣

C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe -pdf "connectionStrings" "."

    下完指令後


    我回去看 webconfig,connectionStrings 的區段確實有恢復到原本的樣子,真是太 cool 了。


小插曲:


    目前,我那個 WebSite1 測試專案下的 webconfig,有加密的區段就 connectionStrings


    這時直接在 IIS 瀏覽專案站台


    它會出現錯誤


    我原本以為,這是因為我沒有做權限的設定,帳戶無法存取金鑰,無法對 webconfig 做解密造成的問題。所以就再用 aspnet_regiis.exe 下了一堆針對 birdshiutest 金鑰存取權限的指令,結果到最後才發現,把那個 entityFramework 區段砍掉就正常了 ....。

    所以,其實我加密完專案的 webconfig 後,IIS 當下其實就能正常解密 webconfig 檔,不需再去做有的沒的權限設定。也有可能,是因為我的網頁不需要讀取 connectionStrings 的值就能正常運作,因為我還有測試把加密過的 connectionStrings 區段給移除,網站還是能正常執行。

    為了確認 IIS 是否真的能正常解密 webconfig 檔,我在 webconfig 檔的 <configuration> 裡加入

<appSettings>
 <add key="test" value="test" />
</appSettings>

    然後下指令來加密,appSettings 區段,我再來去專案下新增一個測試用的 asp 頁面,它的功能就只是讀取 appSetting 裡的 test 值,然後顯示在 Literal。

    aspx頁面

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="birdshiutest.aspx.cs" Inherits="birdshiutest" %>

<!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:Literal runat="server" ID="litTest"></asp:Literal>
        </div>
    </form>
</body>
</html>

    cs頁面

using System;
using System.Configuration;

public partial class birdshiutest : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        litTest.Text = ConfigurationManager.AppSettings["test"].ToString();
    }
}

    接著再瀏覽站台,有看到頁面顯示 test,所以代表 iis 確實能正常解密 "加密後的 webconfig 檔"。


    我在查文章時還有看到這篇,有學到可以用

System.Security.Principal.WindowsIdentity.GetCurrent().Name

    來取得站台目前使用的帳戶,我看是顯示 "IIS APPPOOL\DefaultAppPool"。


匯出與匯入金鑰:

    
    匯出金鑰的語法

aspnet_regiis.exe -px "{金鑰名稱}" {匯出路徑}.xml -pri

    我指令一開始是下這樣,用管理員身份開 cmd 來執行

C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe -px "birdshiutest" C:\birdshiutest.xml -pri

    它跳錯誤給我


    所以我就去查一下那個 -pri 代表什麼。發現是匯出時包含 private key。我記得一開始的時候,加上 -pri 的參數,跑起來是正常的,可能是我後來不知亂動了什麼,導致不能正常匯出它的 private key,為了驗證,我後來還有再新增一個金鑰 container 叫 "birdshiutest2",匯出它,它的匯出功能確實是正常的。


    完成後就能在 C:\ 下面看到 birdshiu2.xml 檔

    再來就可以把金鑰的 xml 檔給丟到其它台電腦,然後匯入金鑰

aspnet_regiis.exe -pi "{金鑰名稱}" {金鑰所在路徑}.xml

    匯入的功能我就沒自己試了,以後有機會再紀錄,聽說匯入金鑰時還會碰上權限設定的問題,這個也之後一併試。


刪除金鑰:


    刪除的 cmd 格式

aspnet_regiis.exe -pz "{金鑰名稱}"

    我在本機上下

C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe -pz "birdshiutest"


    為了確認金鑰真的有刪除,我跑去瀏覽我那個 birdshiutest 頁面


    確實有刪除了,因為它找不到金鑰,所以跳出錯誤。


沒有留言:

張貼留言