If you’ve been following this blog, you know that about 2 and half years ago, I started talking about Group Policy’s precarious role in the typical enterprise’s security posture. Many, if not most, AD shops use GP to perform security hardening on their Windows desktops and servers. This includes everything from tweaking OS settings to turning off NTLMv1 or jiggering with User Account Control (UAC), to controlling who can log into which machines and which AD groups have privileged access on which desktops and servers. All of this is stored within GPOs that, by default, are “world readable” by any authenticated user. Now, this fact has been true for a long time now–really since 2000 when AD & GP shipped–but it’s only become more visible as a potential InfoSec problem in the last few years, largely on the back of tools like Bloodhound, PowerView and Grouper that lay bare the fact that this information can be used to perform all manner of mischief.
Since that time, I’ve focused largely on the defensive side of the equation, and primarily on recommendations to reduce the readability of security-related GPOs to prevent an attacker from easily discovering an organization’s security posture. However, more recently I’ve spent some time thinking about opportunities for more destructive use of GPOs–leveraging existing settings within editable GPOs to perform various evil tasks within an environment. Since GP often impacts most, if not all users and computers in an organization, it’s a very efficient malware distribution mechanism, as I illustrated in a blog post a while back. These types of attacks that inject malicious settings into a GPO, rely on the ability of the attacker to get write permission on a GPO–namely the SYSVOL part of the GPO where most (but not all) GP Client Side Extensions (CSEs) store their settings. Of course, you also need to understand the settings format of the policy area you wish to impact in order to hijack it, and for once, the higgly-piggly way that Microsoft approached the development of CSEs is an advantage here, since pretty much every policy area uses a different schema and data structure to store its settings. Score one for architectural inconsistency!
Three Ways to Cause Trouble
As I’ve been thinking about GP and it’s frailties, I’ve come to the conclusion that there are (at least) three main avenues for an attacker to use GP for their nefarious purposes. Namely,
- Leverage overly permissive read access on GPOs to learn about the security posture of an organization–who has privileged access where, etc. As I mentioned, I’ve blogged about this extensively, and provided suggestions for how to mitigate it.
- Leverage overly permissive write access on GPOs to inject malicious settings into existing GPOs. I talk about this below in the section entitled “GPO Delegation”. PowerView’s New-GPOImmediateTaskcmdlet is a perfect example of taking this approach to inject a scheduled task into a GPO to execute arbitrary code.
- Leverage external paths that are referenced in GPOs and have overly permissive write access. This is a variation on #2 and I really came around to the power of this idea while testing and collaborating with @mikeloss on his excellent Grouper2 utility referenced above. Grouper2 looks for “interesting” stuff in GPOs, which can include everything from Restricted Groups policy granting privileged access to lingering GPP Passwords to, more interesting to me, references to external executables, scripts or installers. I spend more time talking about these external paths below in the section entitled “External Paths”, but @mikeloss really deserves the credit for awakening me to this one.
Let’s talk more about #2 above. The way GPO delegation works is that you grant user, computers or groups, varying levels of access to a GPO, usually in GPMC from the “Delegation” tab on a given GPO, or using PowerShell, and those permissions (which include Read, ReadApply, “Edit Settings” and “Edit Settings, Delete and Modify Security”) get stamped onto the corresponding AD-based Group Policy Container (GPC) object and the GUID-named folder in the Group Policy Template (GPT) (i.e. SYSVOL). Now obviously, AD permissions don’t map 1-1 to NTFS file system permissions, but if you look at both parts of a GPO in the ACL Editor, you will see very similar permissions (see below).
So, as an attacker, you must be able to gain write access to a given GPO’s GPT (or in some cases GPC) in order to compromise that GPO. This is not impossible, obviously, especially if the attacker is able to elevate themselves into an admin role that might have edit permissions on a GPO. But, from a defender’s perspective, it underscores the importance of having tight control over your GPO delegations. GPO edit or create permissions should be delegated to a small handful of sysadmins, and those security principals should be treated as “Tier 0” admins, given the potential environment-wide impact a malicious GPO change can have. More worrisome, if an attacker does gain write access to, for example, the GPT, then it can be very hard to detect these malicious changes if the attacker is modifying settings files directly, rather than going through established GPO change management tools like GP Editor. You essentially have to be looking for file system changes on the GPT to be able to spot most of these unwanted changes, but given that legitimate GPO changes will generate GPT change notifications, you need to also be able to sift through both malicious and valid GPO changes to find the ones that can give you headaches. The good news is that if an attacker has to add net new policy area settings (i.e. they need to call a CSE other than one that has already been deployed) to a GPO, their chances of getting detected go up. This is because, in order for a client (server or workstation) to process a new GPO policy area setting, several changes have to happen in the GPC (e.g. versionNumber incremented and CSE ExtensionGUIDs added correctly to the GPC) to make the client aware of those settings, and that makes it harder for an admin with any decent amount of GP auditing in place, not to notice the tampering. As for the policy areas that are most ripe for this kind of tinkering, check out @_wald0‘s excellent post “A Red Teamer’s Guide to GPOs and OUs“ for some example policy paths that can be mucked with to good effect. This point also argues for keeping GPOs that implement highly “exploitable” policy areas, extra locked-down. Bottom line-lock down who can edit those GPOs!
This brings me to my latest fascination (#3 above), which is the use of “external path” references in GPOs to get around the limitation imposed by admins in #2 above. What do I mean by external paths? Well, really any reference found in a GPO, that points to an executable, script, MSI package or other file that “does something” when called, that exists outside of the normal GPC and GPT (Sysvol) locations. Why are these interesting? Because, even if you are locking down write access to GPOs as I suggested in #2, you could potentially have scripts, executables and MSI packages littering file servers all over your network, with varying degrees of access controls, that are being called and executed by those same locked down GPOs you thought were so safe. So and attacker who fails to get write access to a GPO, can use their read access (ala #1 above) to search out these referenced external paths and try to replace those scripts, exes and MSIs with their own malicious versions (this task is indeed what Grouper2 makes much easier). The next time that GPO is processed by a client, that malicious file is happily executed by the GPO, which is none the wiser. Example of policy areas that can typically reference external paths (i.e. paths outside of the GPC and GPT) include:
- Startup/Shutdown and Logon/Logoff scripts
- GP Software Installation (MSI files)
- GP Preferences Scheduled Tasks
- GP Preferences Printers (with TCP/IP Printers, you can specify an external path for the client to download printer drivers from–neat!)
- GP Preferences Shortcuts, for shortcuts that exist in auto-run locations like Startup
- GP Preferences Files, where you have files that may be copied from arbitrary external locations into auto-run or other “easily executed” local file locations.
To be honest, there are probably more of these types of locations hidden in GP (and I continue to look…). The ones above are the most obvious.
So why do you have to be concerned about these external paths? Well, think about it–the problem of preventing unwanted tampering of GPOs as described in #2 above, is limited. You only have to worry about delegation on those GPOs to keep control of that kind of behavior. But, when you have GPOs that references executable code on external file shares, you now have to extend your scope of concern to EVERY ONE OF THOSE FILE LOCATIONS! How many of you can be sure of the permissions management on random file shares within your environment (let alone your GPOs)? So, if a GPO is calling an executable file or installer that exists on some insecure share, your GPOs now become inadvertent distribution vehicles for whatever random crap an attacker can replace those executables with. And of course, since there’s no CRC checking or other validity checking done within GP, you are at the mercy of whatever files are there (one mitigation to this is the fact that not all policy areas automatically execute their payloads all the time. For example, if a machine has already received a software deployment via Software Installation policy, it won’t re-deploy that malicious MSI under normal circumstances. But any new machines, will of course get the bad package).
So what’s the bottom line for this one? In addition to securing your GPO delegations, first, figure out where your external path references are within your environment, then SECURE YOUR EXTERNAL PATHS!!!!
Hopefully this provides some additional food for thought around protecting your GP environment, and therefore your entire Windows environment. If you are relying on GP today to configure your Windows systems, I can’t stress enough how important it is, from an InfoSec perspective, to ensure those GPOs are buttoned down, and anything external that they call, is treated as ‘within the same domain of concern’ and equally buttoned down. So to summarize the action items here:
- Lock down read access to critical, security-related GPOs to ensure you don’t give away your security posture
- Lock down write access to all GPOs to ensure they aren’t co-opted as an attack vector
- Lock down write access to all external paths referenced by GPOs