UPDATE - 30/06/2016
Official detect and fix script released. See here:
Powershell script to adjust permissions for Authenticated Users on Group Policy
Further information:
Deploying Group Policy Security Update MS16-072 \ KB3163622
Hello,
There is a known issue with the application of particular GPOs once MS16-072 is applied. Click the following link and browse to 'Known Issues' for more information:
MS16-072: Security update for Group Policy: June 14, 2016
In response, I've put together the below PowerShell example to help identify GPOs, from the current domain, that might experience the issue once the update is applied. The output should be the basis for further investigation, i.e. it lists GPOs that may need the 'Authenticated Users' read permission or 'Domain Computers' read permission adding.
In the above image, a red 'WARNING:' message indicates a GPO that may experience the known issue.
There are also three types of 'INFORMATION' message*:
1) yellow - the GPO does not have an 'Authenticated Users' permission, but does contain a 'Domain Computers' permission
2) yellow - the GPO has an 'Authenticated Users' permission that is not 'GpoApply' (Read / Apply) or 'GpoRead' (Read)
3) white - the GPO has the expected 'Authenticated Users' permission.
*NB - all three 'INFORMATION:' messages can be commented out in the script to reduce the output to screen, although the first two may require further investigation
You should also take a look here:
New Group Policy Patch MS16-072– “Breaks” GP Processing Behavior
Cheers,
Mr P. Chap.
Import-Module GroupPolicy
$GPOs = Get-GPO -All
if ($GPOs) {
foreach ($GPO in $GPOs) {
$AuthUser = $null
$DomComp = $null
$AuthUser = Get-GPPermissions -Guid $GPO.Id -TargetName "Authenticated Users" -TargetType Group -ErrorAction SilentlyContinue
$DomComp = Get-GPPermissions -Guid $GPO.Id -TargetName "Domain Computers" -TargetType Group -ErrorAction SilentlyContinue
if (-not $AuthUser) {
if (-not $DomComp) {
else {
elseif (($AuthUser.Permission -ne "GpoApply") -and ($AuthUser.Permission -ne "GpoRead")) {
Write-Host "INFORMATION: $($GPO.DisplayName) ($($GPO.Id)) has an 'Authenticated Users' permission that isn't 'GpoApply' or 'GpoRead'" -ForegroundColor Yellow
else {
Thanks for the script, the Get-GPPermission should be Get-GPPermissions?
I have both in v5! 🙂
Cool script Ian. I like the check for custom permissions. I did an assess-fix script here: https://sdmsoftware.com/group-policy-blog/bugs/new-group-policy-patch-ms16-072-breaks-gp-processing-behavior/
The one thing you may want to add, is a test to see if Domain Computers is in the ACL, since I believe that is sufficient to resolve this to? Also, because I think this only effects GPOs with per-user settings that use sec filtering, I test for that. Reduces the impact a bit.
Thanks, Darren.
Have added the ‘Domain Computers’ test and linked back to your post 🙂
Get-GPPermissions is just an alias for Get-GPPermission 🙂
This is amazing. Thank you for posting this.
If using Security Filtering, we are supposed to add Read permissions Domain Computers for the GPO. This script doesn’t check for that from what I see.
Check added
Thanks for providing this handy script. Much more elegant than the one-liner I wrote this morning!
How do I view the output?
Hey, Anthony – new version will now provide output for non-conflict policies, too.
Too much output for me… So I’ve modified the Write-Output line for the non-conflict policies, and instead used Write-Verbose. Now I get that output just if I specify the -verbose parameter 😉
Sorry I’m a bit of a noob when it comes to this. I do not have any output when I do this powershell. Is it only supposed to return results IF there is one that might conflict and if not, then it will just go back to my regular prompt?
Correct, Nickolas.
New version will now provide output for non-conflict policies, too.
Hey Ian, Thank you very much for the response and thank you very much again for making this script. This has helped me and my teammates tremendously!!
good stuff as always
Thanks
Converted to a function with object output so you can easily export to csv:
Function Test-GPOAuthenticatedUsers{
#Load GPO module
Import-Module GroupPolicy
#Get all GPOs in current domain
$GPOs = Get-GPO -All
#Check we have GPOs
if ($GPOs) {
#Loop through GPOs
foreach ($GPO in $GPOs) {
#Nullify $AuthUser
$AuthUser = $null
#See if we have an Auth Users perm
$AuthUser = Get-GPPermissions -Guid $GPO.Id -TargetName “Authenticated Users” -TargetType Group -ErrorAction SilentlyContinue
#Alert if we don’t have an ‘Authenticated Users’ permission
if (-not $AuthUser) {
$status = ‘Missing Authenticated Users Permission’
} #end of if (-not $AuthUser)
else {
#Alert on a custom permission
if ($AuthUser.Permission -eq “GpoCustom”) {
$Status = ‘Custom Authenticated Users Permission’
} #end of if (-not $AuthUser)
else{
$Status = $true
}
} #end of if (-not $AuthUser)
[pscustomobject]@{‘DisplayName’=$GPO.DisplayName;’ID’=$GPO.ID;’Status’=$status}
} #end of foreach ($GPO in $GPOs)
} #end of if ($GPOs)
}
Test-GPOAuthenticatedUsers | Export-Csv -path c:\temp\gpoauthusersissues.csv -NoTypeInformation
Most of our GPOs are linked to an OU where the computer objects reside. I think this is the case, but just to be clear…”domain computers” isn’t actually necessary if we have an “exception” GPO that overrides another, but only applies to a subset of machines (which are in turn added to security group), correct? It is just necessary that the computer object that needs the access, is able to read. Also, do you need to set the Read permission on the Security Filtering section, or can you just do it on the Delegation tab and only set Read (or…does it require Read+ApplyGPO)?
Have added Domain Computers were no authenticated users also missing on the delegation tab of each GPO for read. But your script still shows me all GPOs in red stating out both are missing.
Is there a way to allow this script to work for older SBS2008 servers? The Import-Module GroupPolicy is not valid in these installs.
Has anyone created a script that will produce this report but also allow you the option to repair? We have a bunch of clients we’re going to have to run this on – it would be nice to have a simple solution, once we “approve it” to have it repaired vs. having us automatically fix each one by hand.
Thanks for the script!
One thing, I found that the script was flagging GPOs where ‘Authenticated Users’ had GPORead instead of GPOApply permissions (which should be an OK situation, correct?).
Changing this line seems to address those being flagged:
#elseif ($AuthUser.Permission -ne “GpoApply”)
elseif ($AuthUser.Permission -ne “GpoApply” -and $AuthUser.Permission -ne “GpoRead”)
For completeness, the same types of checks could probably be added to the “else” section of the ” if (-not $DomComp) ” section but I doubt many environments would have something like that in place.
Again, thanks for putting this together!
Isn’t this over complicating the issue? If I understand correctly, the only change is the *retrieval* of the GPO? Authenticated Users includes computer objects, so if you check the permissions and it has Authenticated Users you are ok. If you do not have Authenticated Users, then you can check if you have Domain Computers. If you have Domain Computers you are ok. If you do not have either you may have an issue. You could add either one and be ok, I would choose to add Domain Computers as a least privilege approach.
Here is a complete plagiarize and hack of the original script. It checks to see if Authenticated Users or Domain Computers permissions exist. If neither exists, it adds Domain Computers with GPORead permissions.
$error.clear()
clear-host
#set to your location for the file containing GPOs that were updated with Domain Computers GPORead permissions
$outfile = “c:\temp\GPO_check.txt”
#Load GPO module
Import-Module GroupPolicy
#Get all GPOs in current domain
$GPOs = Get-GPO -All
$badGPO = 0
#Check we have GPOs
if ($GPOs) {
#Loop through GPOs
foreach ($GPO in $GPOs) {
$checkgpo = $null
$checkgpo = Get-GPPermissions -Guid $GPO.Id -TargetName “Authenticated Users” -TargetType Group -ErrorAction SilentlyContinue
if ($checkgpo -eq $null) {$checkgpo = Get-GPPermissions -Guid $GPO.Id -TargetName “Domain Computers” -TargetType Group -ErrorAction SilentlyContinue}
if ($checkgpo -eq $null) {
Write-Host “WARNING: $($GPO.DisplayName) ($($GPO.Id)) does not have an ‘Authenticated Users’ or ‘Domain Computers’ permission – please investigate” -ForegroundColor Red
$($GPO.DisplayName)|Out-File $outfile -Append
$badGPO++
Set-GPPermissions -Name $($GPO.DisplayName) -TargetName “Domain Computers” -TargetType Group -PermissionLevel GpoRead
}
} #end of foreach ($GPO in $GPOs)
} #end of if ($GPOs)
write-host “Count of updated GPOs $badGPO”
couple things on this.
any way to specify a domain? i have 32 domains i manage. if you log in with an account from domain x on to domain y, the script will take your logon domain.
can we specify a domain controller? since i have 100’s of dc’s, i’m waiting for replication. i tested this on a domain with 2 dc’s. made the change on one dc, and the script still didn’t show. i check the other dc, and replication didn’t go through yet. i’d like to be able to pinpoint 1 dc so that when i make updates, it will report back from that dc, not some other random dc.
sorry I’m definitely learning powershell but by no means can write it. this is a bit above my powershell level.
When a script will be available via the KB homepage, it would be helpful if it can handle a multi-domain forest as well, e. g. by providing a domain parameter.
Nevertheless, thanks for the script.
It sounds like the security change in the MS16-072 patch will affect GPOs with User Settings only, is that right? If I’m understanding this correctly, we have some GPOs that contain only Computer Settings and won’t need to touch those… Can anyone confirm? Thanks
Nice script Ian. I’ve taken your ideas and Darren’s script and rolled them into one big assessment and remediation script here: http://www.jhouseconsulting.com/2016/06/22/script-to-report-on-and-remediate-the-group-policy-security-change-in-ms16-072-1627
Cheers,
Jeremy
Thanks for this!!
May I suggest adding the following to your script for those of us who are not using English (‘Authenticated User’ is ‘Utilisateurs Authentifiés’ in French). So Why not use the SID of groups instead :
# Get ‘Authenticated Users’ group name from SID
$AuthUserSID = New-Object System.Security.Principal.SecurityIdentifier(“S-1-5-11”)
$AuthUserName = ($AuthUserSID.Translate( [System.Security.Principal.NTAccount])).value
# Get ‘Domain Computers’ group name from SID
$DomCompSID = New-Object System.Security.Principal.SecurityIdentifier(“$(((get-addomain).DomainSID).value)-515”)
$DomCompName = ($DomCompSID.Translate( [System.Security.Principal.NTAccount])).value
After that you’ll have to fix ever -TargetName ‘Authenticated Users’ and -TargetName ‘Domain Computers’ to use the new variables :
-TargetName $AuthUserName
-TargetName $DomCompName
Thanks for the script, saved me lot of time.
Great suggestion from Jean-Pierre Paradis. I added this to my script: http://www.jhouseconsulting.com/2016/06/22/script-to-report-on-and-remediate-the-group-policy-security-change-in-ms16-072-1627
Cheers,
Jeremy
Nice script. thnx!
Maybe I did something wrong, but when I run this script I get errors:
At D:\desktop\gpcheck.ps1:20 char:166
+ … omputers’ permission – please investigate†-ForegroundColor Red
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The string is missing the terminator: “.
At D:\desktop\gpcheck.ps1:19 char:20
+ if (-not $DomComp) {
+ ~
Missing closing ‘}’ in statement block or type definition.
At D:\desktop\gpcheck.ps1:17 char:21
+ if (-not $AuthUser) {
+ ~
Missing closing ‘}’ in statement block or type definition.
At D:\desktop\gpcheck.ps1:8 char:25
+ foreach ($GPO in $GPOs) {
+ ~
Missing closing ‘}’ in statement block or type definition.
At D:\desktop\gpcheck.ps1:6 char:12
+ if ($GPOs) {
+ ~
Missing closing ‘}’ in statement block or type definition.
+ CategoryInfo : ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : TerminatorExpectedAtEndOfString
Check the quotation marks….I had the same problem….had to convert the quotation marks in the script to standard ‘single’ and “double” quotes for it to work.
I know this is fir the script but I do have a question about the solution, So am I understanding correctly that it is no longer possible to use Security Filtering by user groups? I have several policies that span multiple OUs and use Security filtering to pick out users by security group. Mainly these are for users that work in multiple departments.
I just published a script to modify the defaultSecurityDescriptor attribute on the Group-Policy-Container schema class object: http://www.jhouseconsulting.com/2016/06/29/script-to-modify-the-defaultsecuritydescriptor-attribute-on-the-group-policy-container-schema-class-object-1668
Hope people find that helpful.
Cheers,
Jeremy
Thanks for sharing the script.
Great
I am having some issues to apply a GPO to a nested group structure using Security Filtering. I wonder whether that’s also caused by the same update. This is the scenario:
AD Users: 1, 2, 3
AD Groups: A, B, C
Group C is a member of Group B
Group B is a member of Group A
GPO filtered to Group A
User1: Member of group A – GPO applies successfully
User2: Member of group B – GPO doesn’t apply (access is denied)
User3: Member of group C – GPO doesn’t apply (access is denied)
GPModeling tells me that all the 3 users
You can one-liner this and return an object instead of text, makes it easier to filter later on…
Get-GPO -All | Select *,@{n=’AuthUser’;e={[bool](Get-GPPermissions -Guid $_.Id -TargetName “Authenticated Users” -TargetType Group -ErrorAction SilentlyContinue)}},@{n=’DomainComputers’;e={[bool](Get-GPPermissions -Guid $_.Id -TargetName “Domain Computers” -TargetType Group -ErrorAction SilentlyContinue)}}