Finding that one GPO Setting in a Pool of Hundreds of GPOs
I had a call recently from a client, they were looking for which Group Policy in their AD had a specific setting in it.
If your organization is like so many, you have dozens or hundreds of Group Policies (GPOs) in your Active Directory. They'll all be meaningfully named, but as the years go by, and multiple admins get all admin-y on your domain, that definition of "meaningful" will tend to drift. Also, you'll often find an admin that says "Oh, that GPO covers the same machines or people that I want to make this change to, I'll add this other thing that GPO"
Long story short, the names of your GPOs will not always be meaningful (to you), and will not always reflect what's inside of them. Or you might have 7-8-9 GPOs that have similar "meaningful names" with very different settings.
Luckily, PowerShell has a way to bail us out of this mess, at least partly.
First, to collect all of your GPOs into one variable, the command:
$GPOs = Get-GPO -All -Domain $DomainName
Next, to dump any one GPO into an XML variable, you can use:
$GPOReport = Get-GPOReport -Guid $gpo.Id -ReportType Xml
(I'm selecting the GPO by GUID in this case)
From there, you can just look for any ASCII string in that XML unicode - any setting or any value.
if ($GPOReport -match $SearchString) {
write-line TA-DA, FOUND IT!!"
}
(not that "-match" is case insensitive by default)
Putting this into one code snip that you can use:
# Set the search string
$SearchString = "Removable"
# init variables
$matchlist = @()
# Get the domain name
$DomainName = $env:USERDNSDOMAIN
# this line is not needed for newer DCs
Import-Module grouppolicy
# collect all GPOs
$GPOs = Get-GPO -All -Domain $DomainName
# Hunt through each GPO XML for the search string
foreach ($gpo in $GPOs) {
$GPOReport = Get-GPOReport -Guid $gpo.Id -ReportType Xml
if ($GPOReport -match $SearchString) {
$matchlist += [string]$gpo.DisplayName
# this line is just to indicate progress - delete if not needed
write-host "Match:" $gpo.DisplayName -foregroundcolor "Green"
}
else {
# this line is just to indicate progress - delete if not needed
Write-Host "No match:" $gpo.DisplayName
}
}
# output results (likely you want to keep this line)
write-host 'String "'$SearchString'" Found in:' -foregroundcolor "Green"
write-host $matchlist -separator "`n" -foregroundcolor "Green"
Once you know which policy or policies your search has narrowed down to, you can just look at the XML files to find the setting, or dump the GPOReport to HTML instead, or heck, just look at the GPO.
My client? They where looking for the GPO that blocked and permitted USB disk access, so our search string was looking for "Removable Storage" settings. Was it in the "USB DRIVES" Group Policy? - nope, that would make too much sense (and was the first place they looked). We ended up finding it in their "Win10 Baseline" policy. If you are curious, those Removable Storage GPO settings are in both User Configuration and Computer Configuration / Policies / Administrative Templates / System / Removable Storage Access
I will likely refine this to also include the individual settings found in some future version, so keep your eyes peeled. But this first version of the script did the job for me - it narrowed down literally about a hundred GPOs down to just 3 that I had to look at (1 was the correct one, and the other two were actually incorrectly set and had to be fixed)
===============
Rob VandenBrink
rob@coherentsecurity.com
Comments
Sam
Jan 17th 2023
1 year ago