At this blog title implies, this is a bit of a science experiment. Many years ago I played around with this idea that, there is nothing in the GP infrastructure that REQUIRES you to use SYSVOL to store the settings files that compose most in-the-box policy areas. At the time, I recall not being able to do this successfully, but clearly I wasn’t doing it right. After a brief “hallway” conversation with someone a few months ago, I thought I’d try it again. Sure enough, it works as expected. What I’m about to describe has both security and operational implications, so bear that in mind as I describe things here.
The first thing to know, is that I differentiate between being able to redirect a GPO’s settings files for GP processing vs. GP management. The technique I describe here works perfectly fine from a GP processing perspective. It does not work at all from a GP management perspective. More on this in a bit.
Before I dive in, I want to revisit how GPOs are structured. Namely, there are two halves to a GPO. The first half, called the GPC or Group Policy Container, is stored as an AD object in the CN=Policies,CN=System container within a given Active Directory domain partition. Each defined GPO has a corresponding, GUID-named object in AD under this container. That’s the GPC. The other half of the GPO is called the GPT or Group Policy Template. The GPT is held in the SYSVOL share and therefore replicated to each DC in the domain. In the SYSVOL share, you’ll find a Policies folder and under that, GUID-named folders corresponding to each GPO defined in the domain. Against, this is the GPO’s GUID, or ID, just like in the GPC. So in the best of times, there should be a 1:1 ratio between GPC objects and GPT folders. At least, you would hope so 🙂
OK, so now that is clear, let’s move on to the meat of things…
Redirecting the GPT
So, how does a GPO know where it’s GPT is? I mean, theoretically it could be hard-coded, but it’s not, at least not at some level. In fact, the reference to the GPT is stored in the GPC, on an AD attribute called gPCFileSysPath, as shown below
Now, this attribute can of course be modified, if you have write permission on the GPC object. And, if you modify this attribute, and provide a different SMB share location, the GPO will happily look for it’s GPT files in that new location. This is indeed what I did in a test I performed. I took an existing GPO, and moved the contents of it’s GPT files from their normal location in SYSVOL, to an arbitrary share on a server I had control over. That share looked like this:
As you can see, the contents of this folder looks like a regular old GPT. I had removed the GPT folder for this GPO completely from SYSVOL and essentially put it’s contents in this share. So, now what happens?
Well, essentially two things happen:
- When a client goes to process this GPO, it queries the GPC (via LDAP) of any GPO that applies to it, and gets the value of gPCFileSysPath. Then it uses that to retrieve the contents of the GPT, in my case, from my arbitrary share. All worked as expected. The setting that I had stored in that redirected GPT showed up on the client machine.
- What doesn’t work as expected, is the management side of the equation. If I go into GPMC and try to view the properties on this GPO, I’ll get this message and the GPMC settings report will show no data.
In addition, if you try to open the GPO in GP Editor, you get a similar message, indicating that the “Network Name cannot be found” and it will simply fail to open the GPO.
So it seems that the management interfaces into GP do indeed hard-code or at least use a relative path from within the normal SYSVOL folder for that domain, to locate the GPT. But, to reiterate, none of these errors effect the ability of the client machines (servers or workstations) to process the GPO at whatever arbitrary location the GPT has been redirected to. This has important security consequences…
If an attacker can get write access on a GPC, they can redirect the GPT for that GPO to any file location of their choosing and inject any manner of bad settings into that GPO by creating their own GPO settings files. Once they’ve done this, your clients will happily process it. I’ve blogged a lot about how to protect Group Policy in general from attacks, and this is yet one more avenue to look at. It’s super important that you know who has write permissions on the CN=Policies,CN=System container within your domain (and especially where those write permissions inherit down to individual GPOs). Normally, this would be controlled by normal GPO delegation, but because this is AD, it is possible to circumvent GPO delegation by mucking with AD delegation directly in the Policies container (or a parent). If you are alerting on AD changes, you should always alert on changes to the gPCFileSysPath attribute–legitimate or otherwise–because they could be indicators of tampering. In addition, if you see the errors like the ones above, that could be a good sign that a GPO has been tampered with. I did up a quick PowerShell script that simply outputs the GPT path registered for every GPO in a given AD domain. It’s an easy, visual way to see if the GPT path has changed from the default, and a good starting point for more sophisticated monitoring. It uses the GPMC PowerShell module, but otherwise should run as expected:
$GPOs = get-GPO -all
foreach ($gpo in $GPOs)
$ldapPath = "LDAP://"+$gpo.Path
[ADSI]$GPC = $ldapPath
$gpo.DisplayName ; $GPC.Properties["gPCFileSysPath"]