使用 PowerShell 测试 GPO 读取权限 (MS16-072 – KB3159398)
上周二补丁,微软发布了安全公告 MS16-072。此更新更改了将组策略下载到计算机的方式,这可能会导致 GPO 无法应用。
这种情况的一个常见症状是用户不再通过 GPO 映射其驱动器。
引用知识库文章 KB3159398:
如果组策略对象缺少经过身份验证的用户组的读取权限,或者如果您正在使用安全筛选并且缺少域计算机组的读取权限,则可能会出现此问题。
组策略不起作用可能是一个大问题,但不用担心,这当然是一个解决方案。再次引用 KB 文章:
要解决此问题,请使用组策略管理控制台 (GPMC.MSC) 并执行以下步骤之一:
- 添加对组策略对象 (GPO) 具有读取权限的经过身份验证的用户组。
- 如果您使用安全过滤,请添加具有读取权限的域计算机组。
-“但是如果我有数百个 GPO 怎么办?这可能要花我一整天的时间! ”
-“如果您使用 PowerShell,则不会! ”
使用 PowerShell 获取 GPO 的权限
首先,我们需要获取域中所有 GPO: 的列表。为此,我们需要 GroupPolicy 模块,该模块随用于组策略的 RSAT 工具一起提供。我通过运行以下命令来确保我拥有该模块:
Get-Module -Name GroupPolicy -ListAvailable现在我可以使用命令 Get-GPO 和参数 -All 列出域中的所有 GPO。
为了获取 GPO 的权限,我使用命令 Get-GPPermission 以及参数 Id(GPO 的 ID)、TargetType(获取用户、计算机或组的权限)和 TargetName(要获取权限的主体的名称)。在这种情况下,我想确保经过身份验证的用户组对我的所有 GPO 具有读取访问权限,以便这将成为我的目标,并且我想从所有 GPO 获取权限,因此我必须循环遍历所有运行 Get-GPPermission 的 GPO每个 GPO 一次。
Import-Module -Name GroupPolicy
# Get all GPOs
$GPOList = Get-GPO -All
$GroupName = 'Authenticated Users'
# Loop
foreach($GPO in $GPOList)
{
Get-GPPermission -Guid $GPO.Id -TargetType Group -TargetName $GroupName
}
这将为我提供所有 GPO 上经过身份验证的用户的权限,在某些情况下,我可能会收到一条错误消息,指出 GPO 没有我要求的安全主体,这意味着经过身份验证的用户无权访问 GPO。啊哈!这就是我正在寻找的不是吗?
如果我将 Get-GPPermission 命令包装在 Try 块中并添加 -ErrorAction Stop 以使所有错误终止,并且通过可捕获,我有一个良好的开始。
获得权限后,我想确保经过身份验证的用户实际上具有“读取”或“应用”权限(“应用”也意味着根据 MSDN 上的文档进行读取)。
如果命令 Get-GPPermission 引发错误或权限不包含“读取”或“应用”,我们将希望确保 GPO 具有正确的权限集,以便返回 GPO 对象。
这导致代码如下所示:
$GPOList = Get-GPO -All
$VerbosePreference = 'Continue'
$GroupName = 'Authenticated Users'
$InvalidGPOList = foreach($GPO in $GPOList)
{
Try
{
$GPPermission = Get-GPPermission -Guid $GPO.Id -TargetType Group -TargetName $GroupName -ErrorAction Stop
if(
$GPPermission.Permission.HasFlag([Microsoft.GroupPolicy.GPPermissionType]::GpoRead)
)
{
$Message = 'GPO: [{0}] is OK!' -f $GPO.DisplayName
}
else
{
$Message = 'No read access found group {0} in GPO: [{1}]' -f $GroupName, $GPO.DisplayName
$GPO
}
}
Catch
{
if($_.FullyQualifiedErrorId -like 'NoSecurityGroupFoundInGpoWithId*')
{
$GPO
$Message = 'No access found group {0} in GPO: [{1}]' -f $GroupName, $GPO.DisplayName
}
else
{
throw
}
}
Finally
{
Write-Verbose -Message $Message
}
}
Write-Output -InputObject $InvalidGPOList
现在我意识到这远非完美,它会给我一个关于经过身份验证的用户具有自定义权限的所有 GPO 的误报,但它会给我一个存在潜在问题的 GPO 列表。
您可以通过使用 ActiveDirectory 模块和 Get-Acl 来获取 GPO 的实际 ACL、检查多个组(您可能希望授予该组“所有计算机”访问权限)甚至使用 Set- 来做得更好。 GPPermission 自动修改任何有问题的 GPO 的权限。如果您做了其中任何一项,请写一篇关于您是如何做的博客文章,然后立即告诉我!