Windows Server 2019上的EventLog.SourceExists失败

时间:2019-02-25 21:09:05

标签: .net iis registry windows-server-2019

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

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

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

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

  

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

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

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

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

谢谢。

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

1 个答案:

答案 0 :(得分:5)

根本原因:

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

默认权限为:

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

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

枚举通常在这样的应用程序中完成:

[System.Diagnostics.EventLog]::SourceExists("Source Name")

即使您尝试使用PowerShell进行枚举,也会遇到“访问被拒绝”的消息。

PS C:\> (gci -Recurse HKLM:\System\CurrentControlSet\services\eventlog).Name

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

解决方案:

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

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

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

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

使用PSexec可以最好地实现以SYSTEM用户身份运行应用程序,该程序可以从Microsoft SysInternals网站(https://docs.microsoft.com/en-us/sysinternals/downloads/psexec)中免费下载

PS C:\> PSexec.exe -accepteula -d -i -s powershell.exe

这将打开一个以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

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