Test GPO read permission with PowerShell (MS16-072 – KB3159398)

Page content

Last patch-tuesday, Microsoft released Security Bulletin MS16-072. This update changes how Group Policies are downloaded to a computer which might cause GPOs to fail to apply.

A common symptom for this is that users no longer get their drives mapped by GPO.

To quote the KB-article KB3159398:

This issue may occur if the Group Policy Object is missing the Read permissions for the Authenticated Users group or if you are using security filtering and are missing Read permissions for the domain computers group.

Group Policies not working can be a great problem, but fear not, these is ofcourse a solution. Once again quoting the KB-article:

To resolve this issue, use the Group Policy Management Console (GPMC.MSC) and follow one of the following steps:

– Add the Authenticated Users group with Read Permissions on the Group Policy Object (GPO).

– If you are using security filtering, add the Domain Computers group with read permission.

-“But what if I have hundreds of GPOs? That might take me all day!”

-“Not if you use PowerShell!”

Get permissions on a GPO with PowerShell

First off we need to get a list of all GPO:s in our domain. To do this we need the module GroupPolicy which comes with the RSAT tools for Group Policies. I make sure I have the module by running the following command:

Get-Module -Name GroupPolicy -ListAvailable

Now I can list all GPOs in the domain with the command Get-GPO and the parameter -All.

To get the permissions of a GPO I use the command Get-GPPermission with the parameters Id (Id of the GPO), TargetType (get permissions for a User, Computer or Group) and TargetName (Name of the principal to get permissions for). In this scenario I want to make sure that the group Authenticated Users has read-access to all my GPOs so that will be my target and I want to get permissions from all GPOs so I will have to loop through all the GPOs running Get-GPPermission once per 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
}

This would give me the permissions for Authenticated Users on all GPOs and on some occations I might get an error stating that the GPO does not have the security principal that I asked for, meaning that Authenticated Users does not have access to the GPO. Aha! This is what I’m looking for isn’t it?

If I wrap my Get-GPPermission command in a Try-block and add -ErrorAction Stop to make all errors terminating and there by catchable I have a good start.

Once I have got the permissions I want to make sure that Authenticated Users actually has either Read or Apply rights (Apply also implies read according to the documentation at MSDN).

If the command Get-GPPermission throws an error or the permissions does not contain Read or Apply we will want to make sure the GPO has the right permissions set so we return the GPO-object.

This resulted in code looking like this:

$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

Now I realize that this is far from perfect, it will give me a false positive on all GPOs where Authenticated Users has Custom permissions, but it will give me a list of GPOs with a potential problem.

You could do this a lot better by using the ActiveDirectory module and Get-Acl to get the actual ACL of the GPO, check for more than one group (you could potentially want to give the group All Computers access instead) and even use Set-GPPermission to automatically modify the permissions on any faulty GPO. If you do any of this, write a blog post about how you did and let med now!