What is UAC?
User Account Control (UAC) is a Windows security feature that forces any new process to run in the security context of a non-privileged account by default. This policy applies to processes started by any user, including administrators themselves. The idea is that we can’t solely rely on the user’s identity to determine if some actions should be authorized.
Although this may seem counterintuitive, imagine the case where user BOB unknowingly downloads a malicious application from the Internet. If BOB is a part of the Administrators group, any application he launches will inherit its access token privileges. So if BOB decides to launch the malicious application and UAC is disabled, the malicious application would gain administrator privileges instantly. Instead, the malicious application will be restricted to a non-administrative access token when UAC is enabled.
UAC Elevation
If an administrator is required to perform a privileged task, UAC provides a way to elevate privileges. Elevation works by presenting a simple dialogue box to the user to confirm that they explicitly approve running the application in an administrative security context:
Integrity Levels
UAC is a Mandatory Integrity Control (MIC), which is a mechanism that allows differentiating users, processes and resources by assigning an Integrity Level (IL) to each of them. In general terms, users or processes with a higher IL access token will be able to access resources with lower or equal ILs. MIC takes precedence over regular Windows DACLs, so you may be authorized to access a resource according to the DACL, but it won’t matter if your IL isn’t high enough.
The following 4 ILs are used by Windows, ordered from lowest to highest:
Integrity LevelUseLowGenerally used for interaction with the Internet (i.e. Internet Explorer). Has very limited permissions.
MediumAssigned to standard users and Administrators’ filtered tokens.
HighUsed by Administrators’ elevated tokens if UAC is enabled. If UAC is disabled, all administrators will always use a high IL token.
SystemReserved for system use.
When a process requires to access a resource, it will inherit the calling user’s access token and its associated IL. The same occurs if a process forks a child.
Filtered Tokens
To accomplish this separation of roles, UAC treats regular users and administrators in a slightly different way during logon:
- Non-administrators will receive a single access token when logged in, which will be used for all tasks performed by the user. This token has Medium IL.
- Administrators will receive two access tokens:
- Filtered Token: A token with Administrator privileges stripped, used for regular operations. This token has Medium IL.
- Elevated Token: A token with full Administrator privileges, used when something needs to be run with administrative privileges. This token has High IL.
In this way, administrators will use their filtered token unless they explicitly request administrative privileges via UAC.
Opening an Application the Usual Way
When trying to open a regular console, we can either open it as a non-privileged user or as an administrator. Depending on our choice, either a Medium or High integrity level token will be assigned to the spawned process:
If we analyze both processes using Process Hacker, we can see the associated tokens and their differences :
On the left, you have a filtered token with medium IL and almost no privileges assigned. On the right, you can see that the process runs with high IL and has many more privileges available. Another difference that may not be so obvious is that the medium IL process is effectively denied any privileges related to being part of the Administrators group.
UAC Settings
Depending on our security requirements, UAC can be configured to run at four different notification levels:
- Always notify: Notify and prompt the user for authorization when making changes to Windows settings or when a program tries to install applications or make changes to the computer.
- Notify me only when programs try to make changes to my computer: Notify and prompt the user for authorization when a program tries to install applications or make changes to the computer. Administrators won’t be prompted when changing Windows settings.
- Notify me only when programs try to make changes to my computer (do not dim my desktop): Same as above, but won’t run the UAC prompt on a secure desktop.
- Never notify: Disable UAC prompt. Administrators will run everything using a high privilege token.
By default, UAC is configured on the Notify me only when programs try to make changes to my computer level:
From an attacker’s perspective, the three lower security levels are equivalent, and only the Always notify setting presents a difference.
UAC Internals
At the heart of UAC, we have the Application Information Service or Appinfo. Whenever a user requires elevation, the following occurs:
- The user requests to run an application as administrator.
- A ShellExecute API call is made using the runas verb.
- The request gets forwarded to Appinfo to handle elevation.
- The application manifest is checked to see if AutoElevation is allowed (more on this later).
- Appinfo executes consent.exe, which shows the UAC prompt on a secure desktop. A secure desktop is simply a separate desktop that isolates processes from whatever is running in the actual user’s desktop to avoid other processes from tampering with the UAC prompt in any way.
- If the user gives consent to run the application as administrator, the Appinfo service will execute the request using a user’s Elevated Token. Appinfo will then set the parent process ID of the new process to point to the shell from which elevation was requested.
Bypassing UAC
From an attacker’s perspective, there might be situations where you get a remote shell to a Windows host via Powershell or cmd.exe. You might even gain access through an account that is part of the Administrators group, but when you try creating a backdoor user for future access, you get the following error:
Powershell
PS C:\Users\attacker> net user backdoor Backd00r /add
System error 5 has occurred.Access is denied.
By checking our assigned groups, we can confirm that our session is running with a medium IL, meaning we are effectively using a filtered token:
Powershell
PS C:\Users\attacker> whoami /groups
GROUP INFORMATION
-----------------Group Name Attributes
============================================================= ==================================================
Everyone Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Local account and member of Administrators group Group used for deny only
BUILTIN\Administrators Group used for deny only
BUILTIN\Users Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\REMOTE INTERACTIVE LOGON Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\INTERACTIVE Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Authenticated Users Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\This Organization Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Local account Mandatory group, Enabled by default, Enabled group
LOCAL Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NTLM Authentication Mandatory group, Enabled by default, Enabled group
Mandatory Label\Medium Mandatory Level
Even when we get a Powershell session with an administrative user, UAC prevents us from performing any administrative tasks as we are currently using a filtered token only. If we want to take full control of our target, we must bypass UAC.
Interestingly enough, Microsoft doesn’t consider UAC a security boundary but rather a simple convenience to the administrator to avoid unnecessarily running processes with administrative privileges. In that sense, the UAC prompt is more of a reminder to the user that they are running with high privileges rather than impeding a piece of malware or an attacker from doing so. Since it isn’t a security boundary, any bypass technique is not considered a vulnerability to Microsoft, and therefore some of them remain unpatched to this day.
Generally speaking, most of the bypass techniques rely on us being able to leverage a High IL process to execute something on our behalf. Since any process created by a High IL parent process will inherit the same integrity level, this will be enough to get an elevated token without requiring us to go through the UAC prompt.
For all the scenarios presented in this room, we assume we have access to the server with an administrative account but from a Medium IL console only. Our goal will always be to access a High IL console without going through UAC.
We will start by looking at GUI-based bypasses, as they provide an easy way to understand the basic concepts involved. These examples are not usually applicable to real-world scenarios, as they rely on us having access to a graphical session, from where we could use the standard UAC to elevate.
Click the Start Machine button to deploy your VM and connect to it via RDP or in the side by side view in Browser:
xfreerdp /v:MACHINE_IP /u:attacker /p:Password321
This machine will be used for all tasks in the room.
Case study: msconfig
Our goal is to obtain access to a High IL command prompt without passing through UAC. First, let’s start by opening msconfig, either from the start menu or the “Run” dialog:
If we analyze the msconfig process with Process Hacker (available on your desktop), we notice something interesting. Even when no UAC prompt was presented to us, msconfig runs as a high IL process:
This is possible thanks to a feature called auto elevation that allows specific binaries to elevate without requiring the user’s interaction. More details on this later.
If we could force msconfig to spawn a shell for us, the shell would inherit the same access token used by msconfig and therefore be run as a high IL process. By navigating to the Tools tab, we can find an option to do just that:
If we click Launch, we will obtain a high IL command prompt without interacting with UAC in any way.
Case study: azman.msc
As with msconfig, azman.msc will auto elevate without requiring user interaction. If we can find a way to spawn a shell from within that process, we will bypass UAC. Note that, unlike msconfig, azman.msc has no intended built-in way to spawn a shell. We can easily overcome this with a bit of creativity.
First, let’s run azman.msc:
We can confirm that a process with high IL was spawned by using Process Hacker. Notice that all .msc files are run from mmc.exe (Microsoft Management Console):
To run a shell, we will abuse the application’s help:
On the help screen, we will right-click any part of the help article and select View Source:
This will spawn a notepad process that we can leverage to get a shell. To do so, go to File->Open and make sure to select All Files in the combo box on the lower right corner. Go to C:\Windows\System32
and search for cmd.exe
and right-click to select Open:
This will once again bypass UAC and give us access to a high integrity command prompt. You can check the process tree in Process Hacker to see how the high integrity token is passed from mmc (Microsoft Management Console, launched through the Azman), all the way to cmd.exe: