Make Sure Your Standard Users are Really Standard Users

I had my worldview challenged today.

I had gone on record saying that, if you are deploying to Standard Users, then UAC really can’t hurt you – it can only help you.

But then I saw something I really did not understand – two identical machines, side by side. Both of them logged in as a standard user. One machine had UAC turned on, the other had it turned off. And there was a piece of software that only worked with UAC turned off.


After poking around with tools for a while, I just went on in with the debugger. And I noticed that the application was launching another application, and that this application would have triggered installer detection, and their group policy was configured to automatically deny elevation requests. However, I then verified their group policy that installer detection was turned off, so that couldn’t be it.

Hmm… it must be manifested. While that wouldn’t explain why it worked with UAC turned off, it only took a second to shim it up with RunAsInvoker (which trumps a manifest) and have a go – sure enough it worked!

So, I brought the exes over to a machine that had dev tools on it so I could crack them open and look for the manifests I was sure were there, and indeed they were. But they weren’t manifested as requireAdministrator – they were manifested as highestAvailable. That’s strange – that should work as a standard user, since you don’t generate a split token and highest available is just you as you are.

So, why would a highestAvailable manifest cause an app to fail as a standard user? Well, the answer is that it shouldn’t. The problem was that their standard users weren’t actually standard users.

You see, I flipped around in their group policy and noticed that they had the UserRightsAssessment set so that the Users group had Back up files and directories and Restore files and directories.

Yowzers. This adds SeBackupPrivilege and SeRestorePrivilege to the token. These are pretty ridiculously powerful privileges. They let you read and write any file you want without an AccessCheck. To quote the DDK, each privilege “obviates the need for any ACL-based security check.” And there is really no reason to have ACLs on your files giving you the illusion of security if you simply allow everyone to bypass them on a whim, eh? We recognize this, and we then split the token.

So, their “standard users” were not exactly standard users – they were generating split tokens, and this highestAvailable-manifested app was having the elevation request automatically denied. Problem solved – time to fix that policy. (There’s not point in having it, now is there, since they’ll never be able to elevate to the token that actually contains their privileges?)

And my worldview was able to continue. Crisis averted.

Comments (3)

  1. Hi Chris,

    Enjoying your blog.  Thought you should know that I had similar problems when I made all users a member of the Power Users group for backward compatibility purposes (a strategy some docs recommend).

    Although Power Users aren’t supposed to gain any additional rights, they get a split token anyway.  Then we experience the elevation hell for everything that wants the HighestAvailable token.

    There is also a strange interaction with the EnableLinkedConnection key that was discussed in a previous article of yours concerning mappings.  The key was supposed to enable mappings to be visible to the different tokens.  This did work for a time – but as of SP1, only the admin token gets the merged mappings from the standard token – the Power User’s full token must now go without.  I have opened a premier support ticket about this but it looks like I may be told that Power User support wasn’t part of the spec…

  2. cjacks says:

    If you don’t have ACLs set up specifically for Power Users that you can’t change in the foreseeable future, I wouldn’t use it. It has been deprecated.