Common Vista/Win7 scenario: the app you’ve written runs with elevated permissions, but then needs to start another program as the non-elevated desktop user. For example, you want to display web content. Now, you could just launch the web browser from your app, and let the web browser run as admin. What could go wrong? (Hint: the correct answer will include the word “catastrophic”)
A very common mistake that programmers make is to grab a copy of the elevated, High Integrity Level access token from the current process and then “dumb it down”. I.e., disable powerful group memberships, remove powerful privileges, and change the integrity level to Medium. They then launch the new process with that “dumbed down” token. This breaks for a number of reasons.
First and foremost, that approach makes the invalid assumption that the elevated app is running under the same user identity as the desktop user who originally logged on. This is the new “LUA bug” of Vista and Win7. (Refresher: “LUA” = “limited user account”; “LUA bug” = failure that occurs when running as LUA and not administrator. #1 cause of LUA bugs: assumption that the end user will be an administrator.) In Vista/Win7, everything runs as “LUA” by default, unless you specifically allow something to run elevated. If you’re a member of the Administrators group, by default this involves a simple “consent” prompt. The resulting app still runs as you, but with full admin rights. If you’re not a member of Administrators, the elevation prompt requires the credentials of another account that is a member of Administrators. The resulting app then runs as a different user. A number of apps fail to take this second scenario into consideration. “Dumbing down” the current process token is one example of that kind of failure. The new program runs with reduced permissions, but not as the intended user.
There are at least a couple of other failures in that approach too, that are more obscure. Let’s say you are a member of Administrators. When you log on, the Windows LSA (Local Security Authority) generates two access tokens in two separate LSA-managed logon sessions. One is the fully privileged, full-admin token; the other is the standard-user version, which is marked as linked to the full-admin token. When you create a “dumbed-down” copy of the elevated one, the new token is still associated with the elevated session, and marked as being the “high half” of a split token. As a result, if you start Internet Explorer with that token, Protected Mode will be disabled. Also, if your “dumbed-down” process tries to launch an elevated app, it will simply launch the new process with the “dumbed-down” token, since it’s already marked as “elevated.”
So here’s one sequence that works well:
I’ve attached an example C++ project, built with VS2008 and the MFC AppWizard, and tested with x86 and x64 builds. The meat of the sample is in RunAsDesktopUser_Implementation.cpp. I’m sure it can be done in managed code, but that will be someone else’s project, not mine.
Please note that there are a bunch of caveats about this approach: