Windows Server 2019上的EventLog.SourceExists失败

bbm*_*bbm 4 .net iis registry windows-server-2019

我正在使用.Net Framework 4.7.2在Windows Server 2019上测试ASP.NET应用程序。IIS应用程序被设置为模拟没有管理特权的用户。

EventLog.SourceExists在尝试创建新的源之前,应用程序调用以检查事件日志源是否存在。我了解此方法需要管理特权才能在现有事件日志中搜索源[1]。完成此操作的另一种方法是,我明确授予用户对注册表项HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog和所有子项的读取权限。

这适用于Windows Server 2019(2016、2012 R2、2018)之前的版本。

测试时,该相同应用程序在Windows Server 2019上失败,但例外。

找不到源,但是无法搜索某些或所有事件日志。不可访问的日志:状态。

在运行procmon时,尝试打开“状态”事件日志的注册表项时看到“访问被拒绝” HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\State

“状态”注册表项是Windows Server 2019的新增功能。它也受到保护-它归SYSTEM拥有,并且管理员仅限于只读。尝试授予用户读取权限时,我被拒绝访问。结果,以非管理员用户身份运行的应用程序Inaccessible logs: State在调用EventLog.SourceExists时失败。

我意识到我可以拥有State注册表项的所有权并添加我的用户。但是,在执行此操作之前,我想看看是否有人知道Windows Server 2019中的此新注册表项(eventlog)。

谢谢。

[1] https://docs.microsoft.com/zh-CN/dotnet/api/system.diagnostics.eventlog.sourceexists?view=netframework-4.7.2

小智 5

根本原因:

HKLM \ SYSTEM \ CCS \ Services \ EventLog树中的“状态”配置单元具有奇怪的安全配置。因此,任何尝试枚举事件源的应用程序最终都会遇到“访问被拒绝”异常并退出。

默认权限是:

  • 系统(完全控制)
  • EventLog(完全控制)
  • 管理员(读取密钥)

它们不会像“安全性”配置单元那样被继承。相反,名为“ Parameters”的第二个新配置单元继承了权限。

枚举通常在以下应用程序中完成:

[System.Diagnostics.EventLog]::SourceExists("Source Name")
Run Code Online (Sandbox Code Playgroud)

即使当您尝试使用PowerShell进行枚举时,也会遇到“访问被拒绝”的提示

PS C:\> (gci -Recurse HKLM:\System\CurrentControlSet\services\eventlog).Name
Run Code Online (Sandbox Code Playgroud)

虽然我不知道“状态”配置单元到底在做什么(微软对此不是很详细),但我找到了一种解决方法。

解:

  1. 交互式解决方案,使用REGEDIT:

    a)使用“ PSexec”作为系统运行REGEDIT,并b)使用REGEDIT的UI,为IIS_IUSRS或与您的服务或IIS应用程序池一起运行的任何任意帐户的“状态”配置单元授予读取权限

  2. 使用PowerShell的脚本化方法:

    a)使用'PSexec'将PowerShell作为SYSTEM运行,以及b)使用'Get-ACL'/'Set-ACL'cmdlet,为IIS_IUSRS或服务或IIS应用程序池运行的任何任意帐户的'State'配置单元授予读取权限与

通过使用PSexec可以最好地实现以SYSTEM用户身份运行应用程序,可以从Microsoft SysInternals站点(https://docs.microsoft.com/zh-cn/sysinternals/downloads/psexec)免费下载该文件。

PS C:\> PSexec.exe -accepteula -d -i -s powershell.exe
Run Code Online (Sandbox Code Playgroud)

这将打开一个以NT AUTHORITY \ System身份运行的PowerShell窗口。在这里,使用REGEDIT更改“状态”配置单元上的服务用户帐户或IIS应用程序池用户的权限。或者,使用Get-ACL / Set-ACL cmdlet以脚本方式进行相同操作。“读取密钥”权限已足够;无需“完全控制”。

PS C:\> $hive = HKLM:\System\CurrentControlSet\services\eventlog\state; $acl = Get-ACL $hive; $rule = New-Object System.Security.AccessControl.RegistryAccessRule ("IIS_IUSRS","ReadKey","ContainerInherit","None","Allow"); $acl.SetAccessRule($rule); $acl |Set-ACL $hive
Run Code Online (Sandbox Code Playgroud)

现在,您的应用程序应该能够枚举运行它的计算机上的所有事件源,并在枚举找不到的情况下创建一个事件源。