PsExec, User Account Control and Security Boundaries
I introduced the -l switch to PsExec about a year and a half ago as an easy way to execute processes with standard-user rights from an administrative account on Windows XP. In Running as Limited User – The Easy Way I described how PsExec uses the CreateRestrictedToken API to create a security context that’s a version of the one your account is using, only without membership in the local administrators group or any of the privileges, such as Debug Programs, that are assigned to administrators. A process running with that kind of security context has the privileges and accesses of a standard user account, which prevents it from modifying system files and Registry keys or exercising privileges, like loading a device driver, that only administrators can perform.
There’s only one catch to the virtual sandbox the restricted token creates: processes running in the sandbox are running as you, and so can read and write any files, Registry keys, and even other processes to which your account has access. That caveat creates major gaps in the walls of the sandbox and malicious code written with awareness of the restricted environment could take advantage of them to escape and become full administrator. An easy way out is for the malware to simply use OpenProcess to gain access to one of your processes running outside the sandbox and to inject into it code and a thread to execute the code. Because your other processes are running as you and the Windows security model creates default permissions that grant your account full access to your processes, a sandboxed process will be able to open them. Another way out is to send window messages from the limited process to a normal process, like Explorer, and drive the normal process with synthesized mouse and keyboard input so that it executes code at the direction of the malware.
Given these holes, why do I still recommend using the PsExec feature to run processes with limited rights on Windows XP if you would rather use an administrator instead of standard user account? Because this type of sandbox has not been commonly used, malware authors haven’t bothered with writing the code necessary to escape and so they run into the walls.
Windows Vista changes that, however, because it uses an enhanced form of this sandbox in User Account Control (UAC) and Protected Mode Internet Explorer (IE). Let’s look at Vista’s version of the sandbox, how PsExec’s update lets you run programs in it, and explore its security implications.
UAC creates an alternate model where all users, including administrators, run with standard user rights. Executables that require administrative rights include a requestedExecutionLevel key in their manifest - XML embedded in their executable - that specifies “requireAdministrator”. When an administrator executes such an image, in its default configuration UAC presents a Consent dialog that asks permission for the image to run with administrative rights. Standard users see a similar dialog, but must enter the credentials of an administrative account to unlock administrative rights.
The act of giving an executable administrative rights is called “elevation” in UAC. Whether you elevate from a standard user account (Over the Shoulder – OTS - elevation) or from an administrative account (Admin Approval Mode – AAM - elevation), you create processes that have administrative rights on the same desktop as those that have standard user rights. Processes elevated from a standard user account run in a different account from those with standard user rights, so the Windows security model defines a wall around the elevated process that prevents the non-elevated processes from writing code into those that are elevated. However, the standard Windows security model does not prevent non-elevated processes from sending fake input into elevated processes, nor does it create a sandbox around the non-elevated processes of administrative users to stop the processes from compromising the administrator’s elevated processes. Windows Vista therefore introduces the Windows Integrity mechanism, which supplies additional fencing for the sandbox surrounding less-privileged processes.
In Vista’s integrity model, every process runs at an integrity level (IL) and every securable object has an integrity level. The primary integrity levels are low, medium (the default), high (for elevated processes) and system. The windowing system honors integrity levels to prevent lower-IL processes from sending all but a few informational window messages to the windows owned by processes of a higher IL, calling this protection User Interface Privilege Isolation (UIPI). The security model also changes in Vista to only allow a process to open an object for write access if the process IL is equal to or higher than that of the object. Further, to prevent access to secrets stored in memory, processes can’t open processes of a higher IL for read access.
If you add the Integrity Level column to Process Explorer’s display, as seen in the screenshot below, you can see that system processes, including Windows service processes, run at System IL. Most processes of your logon session run at Medium, any processes you elevated are at High, and Internet Explorer (IE) runs at Low when you have Protected Mode enabled. You can use the built-in icacls.exe utility to view and change the ILs of files and directories and the Sysinternals AccessChk tool shows ILs of files, directories, registry keys, and processes. Objects have a default IL of medium and you can use AccessChk’s -e option to search for objects that have an explicit IL.
The new version of Psexec takes advantage of the enhanced Vista sandbox when you specify the -l switch, running the executable you specify with a standard user token at low IL. The sandbox PsExec creates is almost identical to the one surrounding Protected Mode IE and you can feel your way around the walls by launching a command prompt or Regedit at low IL and then seeing what you can modify. For example, I launched the command prompt seen below at low IL with this command: psexec -l -d cmd.exe
I first determined my profile’s temporary directory with the “set” command. When I tried to create a file in that directory I was denied access because the directory has a default IL of Medium, which is indicated by the fact that there’s no IL specified in Icacl’s output. Then I changed to Protected Mode IE’s temporary directory, which has an IL of Low, and successfully created a file.
As you experiment you’ll find that your actions are limited, but there are some design boundaries that you should be aware of. First, with the exception of processes and threads, the wall doesn’t block reads. That means that your low-IL command prompt or Protected Mode IE can read objects that your account (the standard-user version if you’re a member of the administrator’s group) can. This potentially includes a user’s documents and registry keys.
Even the ability of a process at low IL to manipulate objects of a higher IL isn’t necessarily prevented. Since processes running at different integrities are sharing the same desktop they share the same “session”. Each user logon results in a new session in which the processes of the user execute. The session also defines a local namespace through which the user’s processes can communicate via shared objects like synchronization objects and shared memory. That means that a process with a low IL could create a shared memory object (called a section or memory-mapped file) that it knows a higher IL process will open, and store data in the memory that causes the elevated process to execute arbitrary code if the elevated process doesn’t properly validate the data. That kind of escape, called a squatting attack, is sophisticated, requires the user to execute processes in a specific order and requires knowledge of the internal operation of an application that is susceptible to manipulation through shared objects.
However, let’s be clear that no matter how difficult to pull off, the mere possibility of such a breach of a sandbox wall implies that ILs, in and of themselves, do not define security boundaries. What’s a security boundary? It’s a wall through which code and data can’t pass without the authorization of a security policy. User accounts running in separate sessions are separated by a Windows security boundary, for example. One user should not be able to read or modify the data of another user, nor be able to cause other users to execute code, without the permission of the other user. If for some reason it was possible to bypass security policy, it would mean that there was a security bug in Windows (or third-party code that allows it).
It should be clear then, that neither UAC elevations nor Protected Mode IE define new Windows security boundaries. Microsoft has been communicating this but I want to make sure that the point is clearly heard. Further, as Jim Allchin pointed out in his blog post Security Features vs Convenience, Vista makes tradeoffs between security and convenience, and both UAC and Protected Mode IE have design choices that required paths to be opened in the IL wall for application compatibility and ease of use.
Not requiring a user to type Ctrl+Alt+Delete to verify that the credential dialog UAC presents for an OTS elevation is one example of security balanced against usability, but there are others, like the ones I describe in my TechEd/ITForum talk User Account Control Internals and Impact on Malware (Jim’s post describes some of the ways you can enhance security while tipping the balance against ease of use, like configuring Windows to require Ctrl+Al+Delete for the credential dialog). For instance, having your elevated AAM processes run in the same account as your other processes gives you the convenience of allowing your elevated processes access to your account’s code and data, but at the same time allows your non-elevated processes to modify that same code and data to potentially cause an elevated process to load arbitrary code.
Because elevations and ILs don’t define a security boundary, potential avenues of attack , regardless of ease or scope, are not security bugs. So if you aren’t guaranteed that your elevated processes aren’t susceptible to compromise by those running at a lower IL, why did Windows Vista go to the trouble of introducing elevations and ILs? To get us to a world where everyone runs as standard user by default and all software is written with that assumption.
Without the convenience of elevations most of us would continue to run the way we have on previous versions of Windows: with administrative rights all the time. Protected Mode IE and PsExec’s -l option simply take advantage of ILs to create a sandbox around malware that gets past other security defenses. The elevation and Protected Mode IE sandboxes might have potential avenues of attack , but they’re better than no sandbox at all. If you value security over any convenience you can, of course, leverage the security boundary of separate user accounts by running as standard user all the time and switching to dedicated accounts for unsafe browsing and administrative activities.
Look for my in-depth article on UAC internals in the June issue of TechNet Magazine, and if you want if you want to learn about other changes in Windows Vista then check out the first of my three-part Inside the Vista Kernel article series in the February issue of TechNet Magazine.