8

我正在使用 .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

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

我意识到我可以拥有State注册表项并添加我的用户。但是,在我这样做之前,我想看看是否有人知道 Windows Server 2019 中的这个新注册表项(事件日志)。

谢谢。

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

4

1 回答 1

8

根本原因:

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

默认权限是:

  • 系统(完全控制)
  • 事件日志(完全控制)
  • 管理员(读取密钥)

它们不是继承的,就像“安全”蜂巢一样。相反,名为“Parameters”的第二个新配置单元继承了权限。

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

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

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

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

虽然我不知道“状态”蜂巢到底在做什么(微软对此并不十分详尽),但我找到了解决此问题的方法。

解决方案:

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

    a) 使用 'PSexec' 以 SYSTEM 身份运行 REGEDIT 和 b) 使用 REGEDIT 的 UI,为 IIS_IUSRS 或您的服务或 IIS 应用程序池运行的任何任意帐户授予对 'State' 配置单元的读取权限

  2. 脚本方法,使用 PowerShell:

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

以 SYSTEM 用户身份运行应用程序最好使用 PSexec,它可以从 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

您的应用程序现在应该能够枚举运行它的机器上的所有事件源并创建一个事件源(如果枚举未找到它)。

于 2019-07-30T12:46:22.953 回答