Windows 安全事件出現與帳號 「NT Service\MSSQLSERVER」、「NT Service\MSSQLAGENT」 相關的登入稽核事件, 隱約知道它是 SQL 伺服器使用的帳號。IIS AppPool\* 帳號我知道,但還我真沒研究過 NT Service\* 帳號是什麼來歷,於是,Windows 豆知識單元又來了!

Windows 2008 R2 起加入了虛擬帳號(Virtual Account)的概念,它是一種用於簡化服務管理的受控本機帳號(Managed Local Account)。這些虛擬帳號由系統自動建立及管理,帳號名稱為 NT SERVICE\<SERVICENAME>,能在網域環境用該主機電腦帳號 <domain_name>\<computer_name>$ 存取網路資源,概念很類似 NETWORK SERVICE 本機帳號,最大的不同是虛擬帳號能隔離各服務的權限範圍,讓檔案或資源只授權特定服務存取,與 IIS AppPool 虛擬帳號異曲同工。而觀察 SQL .mdf 資料檔的 NTFS 存取權限,可發現存取帳號包含 MSSQLSERVER 帳號(NT SERVICE\MSSQLSERVER),足以印證這點。

在 Windows 2008 之前,SQL DataBase Engine 跟 SQL Server Agent 預設執行帳號為 NETWORK SERVICE,Windows 2008R2 / Windows 7 起改用 NT SERVICE\MSSQLSERVER 及 NT SERVICE\SQLSERVERAGENT 參考 (若是 Named Instance,帳號名稱則為 NT SERVICE\MSSQL$<instance_name>、NT SERVICE\SQLAGENT$<instance_name> ),也就是事件檢視器看到的帳號。

虛擬帳號由 Windows 自動建立,密碼會自動設定更新,不需擔心密碼外流、敲錯。而且 NT SERVICE\* 帳號並非微軟產品才能用,Windows 服務註冊即會產生,我們自己寫的 Windows 服務也可善用它實現更嚴謹的權限管控。

最後,用 Mimial API 寫個 Windows Service 實地演練作為文章的結尾。

以下是個簡單的 Minimal API,主網址傳回目前程式的執行帳號:

using System.Security.Principal;
using Microsoft.Extensions.Hosting.WindowsServices;
var webApOpts = new WebApplicationOptions {
    ContentRootPath = WindowsServiceHelpers.IsWindowsService() ?
        AppContext.BaseDirectory : default,
    Args = args
};
var builder = WebApplication.CreateBuilder(webApOpts);
builder.Host.UseWindowsService();
var app = builder.Build();
app.MapGet("/", () => "Account = " + WindowsIdentity.GetCurrent().Name);
app.Run();

編譯成 exe 並註冊成 Windows Service:(實作細節請參考延伸閱讀)

dotnet publish -c Release -r win-x64 -p:PublishSingleFile=true --no-self-contained  
sc create viracnttest binPath="D:\Lab\VirAcntTest\bin\Release\net6.0\win-x64\VirAcntTest.exe --urls http://localhost:22321"  

由於服務註冊名稱為 viracnttest,Windows 將會建立名為 NT SERVICE\viracnttest 的虛擬帳號。用電腦管理 UI 將服務登入身分設成 NT SERVICE\viracnttest (密碼留白即可),重啟服務後,可觀察到執行身分已變成 NT SERVICE\viracnttest,成功!

【延伸閱讀】

Introduce to the virtual account concept for Windows services.


Comments

Be the first to post a comment

Post a comment