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.