Bypass Windows 10 User Group Policy (and more) with this One Weird Trick
I‘m going to share an (ab)use of a Windows feature which can result in bypassing User Group Policy (as well as a few other interesting things). Bypassing User Group Policy is not the end of the world, but it’s also not something that should be allowed and depending on User Group Policy setup, could result in unfortunate security scenarios. This technique has been tested against Windows 7 and Windows 10 Enterprise x64 (10.18363 1909) and does not require admin access. Leveraging this trick has to do with how the user account registry is loaded upon login, so let’s start this off by understanding a bit about what happens when a user logs into a Windows account.
When You Log In
One of the many things that occur as you log into a Windows account, is the user-defined settings are loaded for the account. These settings are loaded from the “User’s Registry Hive”, which you may know of as HKEY_CURRENT_USER whenever you pull up regedit. This hive contains user-related settings for the operating system and various applications that may be installed. This “Hive” is actually a file that is stored on the filesystem which can be found at “%USERPROFILE%\ntuser.dat”. Upon login, ProfSvc (user profile service) locates this file and calls NtLoadKeyEx in order to load the Registry Hive. If a user wishes to make registry key modifications during their logon session, it must go through proper Microsoft APIs which in turn check permissions of the keys you want to modify (as if it were a mini file system itself).
If we fire up ProcMon with “boot logging” enabled, there is an interesting behavior in the ProfSvc service as we log onto a machine.
ProfSvc just checked if “%USERPROFILE%\ntuser.man” file exists, before it loaded “%USERPROFILE%\ntuser.dat”. What is “ntuser.man”? It’s exactly like ntuser.dat (being that its a user profile registry hive), however, it’s for cases where you want to establish a “Mandatory Profile”. We know the %USERPROFILE% path is writable by non-admin of course, so we can achieve some interesting results by dropping our own crafted “ntuser.man”.
Bypassing User Group Policy
Group Policy is a Microsoft feature that allows Domain Administrators to manage settings and enforcements for users on their network. An administrator can configure these Group Policy settings at the computer level and/or for the user level. For user policies, these settings are pushed out to a domain user’s account upon login and stored in the “%USERPROFILE%\ntuser.dat” hive. These user policies are read-only for Domain Users, preventing them from being changed.
Since we can swap out an entirely new hive, we can bypass or modify any of these “protected” user group policy enforcements.
We simply need to:
- Craft our own User Registry hive named “ntuser.man”,
- Remove or apply whatever policies key/values we want in the hive.
- Drop the file in target machine’s %USERPROFILE% path
- Logout and log back in.
But Windows will Resync Group Policy Rules and Override these Changes…Right?
Those familiar with User Group Policy know that the policies resync and reapply themselves upon login (as well as regular intervals while logged on), thus overriding any modified policies that might have been made. Even if we attempt to prevent this overriding by removing “SYSTEM” from the ACL of our crafted key, GpSvc (The Windows Group Policy Client) will detect this and correct the ACL upon login to regain writable permissions, then rewrite the Group Policy settings.
But… there is a way to get around this. I looked at how this ACL modification was being done inside GpSvc. When GpSvc comes across our “Policies” subkey, it calls its internal function ForceRegCreateKeyEx, which tries to open one of our “Policy” subkeys with writable permissions, and if it fails, calls AddPolicyPermissionOnKey to take ownership of key and restore “SYSTEM” with writable permissions on key, then reopen the key and overwrite the Group Policy entries.
Looking at the AddPolicyPermissionOnKey routine, I noticed it modifies the ACL of the subkey to add “SYSTEM”, but it does not remove any existing ACL entries. This means if we set an explicit entry to “DENY” SYSTEM writable permissions, then it will effectively block “SYSTEM” from obtaining writable permissions since our “DENY” rule will take precedence over the “ALLOW” rule that it tries to add.
With this additional trick, it’s quite straight forward, and the GIF below demonstrates this.
The impact of this is largely “policy configuration” dependent, and while this could potentially be a threat from a malware perspective, it is more likely a threat from a rogue Domain User trying to break out of restrictions imposed by a Domain Admin.
It’s worth mentioning that this quirk can result in things other than bypassing User Group Policy.
- Single File Code Execution — Some exploits may be able to drop a file somewhere on the Windows filesystem as non-admin. If the exploit dropped a “%USERPROFILE\ntuser.man”, with an autostart registry key to execute a file off of a remote SMB share, then the exploit now gained reliable code execution simply by dropping one non-executable file.
- Antivirus/EDR Bypass — Some Antivirus/EDR products may only monitor registry modifications by intercepting Registry APIs or Kernel callbacks. In the case where you make a registry change by replacing the entire hive, this could circumvent monitoring and detection.
- Denial of Service — By dropping an empty ntuser.man file in %userprofile%, ProfSvc will fail to load registry and thus prevent the user from logging in, requiring Safe Mode boot or backup Admin account to remove offending ntuser.man file.
Proof Of Concept
(CAUTION — THIS CAN DAMAGE A WINDOWS ACCOUNT, do NOT try this on a Domain machine that you are not Administrator for. I recommend trying this in a test virtual machine if you are curious. If you do end up trying this on a personal machine, don’t try it on an Administrator account, as an Administrator account will be required to go in and delete the ntuser.man file when done:
1. Crafting Ntuser.man
- On an entirely separate (same version) Windows machine which you have Administrator access to, copy any user’s registry hive from %USERPROFILE%\ntuser.dat file to a different folder. Note, you will need to make sure this user is not logged in so that you can actually copy this file.
- Under the Administrator account, start regedit.exe, load this copied registry hive by selecting HKEY_LOCAL_MACHINE key, and clicking File->Load Hive…
- Under the newly loaded reg hive, clear or add any policies under the appropriate policy reg path, for example, many user policies are stored in \Software\Microsoft\Windows\CurrentVersion\Policies\.
- At the root of the hive you loaded in regedit, change permissions to allow “Everyone” full control (read/write/etc) and propagate these permissions for all subkeys.
- Depending on the “Policy” you want to override or add, you will need to find the corresponding subkey related to it, as they are not all stored under one key in the User’s registry. For example, in the “Remove Task Manager ‘’ scenario, the value that defines this is in the \Software\Microsoft\Windows\CurrentVersion\Policies\System key. So “System” subkey is where you would add a “DENY” rule, to deny SYSTEM “Write/Create” privileges for that key. This ensures GpSvc can’t overwrite it.
2. Drop Ntuser.man
- Before continuing, ensure sure you have a backup account on the machine with Administrator privileges separate from the account you are testing on. If not — create one now, as this will be needed to delete the PoC file.
- Copy the registry hive you crafted as “%USERPROFILE%\ntuser.man” to the machine which you want to override User Group Policy for.
- Log off and Log back on. You may see a Windows welcoming screen, let this finish and now all User Group Policies have been overridden with what you have in ntuser.man.
3. Remove Ntuser.man
- After testing PoC, logout and login with the Administrator account to remove the “ntuser.man” file from the user’s profile path.
We reached out to Microsoft to report this issue as per our 90-day disclosure policy. While they were able to fully replicate this issue, Microsoft deemed this to be expected behavior and not a security issue. While I understand it’s not a critical issue, it’s my belief that modifying protected policies like this is crossing a security boundary, regardless of how it’s done.