4

I expected this code:

WindowsPrincipal principal = new WindowsPrincipal( WindowsIdentity.GetCurrent() );
public bool UserHasAdminRights( WindowsPrincipal principal, WindowsBuiltInRole role )
{
  bool isAdmin;

  // get the role information of the current user
  if ( principal.IsInRole( role ) )
  {
    isAdmin = true;
  }
  else
  {
    isAdmin = false;
  }
  return isAdmin;
}

to return true when a user is in the Built-in Administrators group.

HOWEVER

MSDN for IsInRole states:

In Windows Vista, User Account Control (UAC) determines the privileges of a user. If you are a member of the Built-in Administrators group, you are assigned two run-time access tokens: a standard user access token and an administrator access token. By default, you are in the standard user role. When you attempt to perform a task that requires administrative privileges, you can dynamically elevate your role by using the Consent dialog box. The code that executes the IsInRole method does not display the Consent dialog box. The code returns false if you are in the standard user role, even if you are in the Built-in Administrators group. You can elevate your privileges before you execute the code by right-clicking the application icon and indicating that you want to run as an administrator.

Question is how do I modify this code so that it returns true, if the user is in the built-in Admin group, WITHOUT requiring the user to elevate permissions during/before runtime?

H H
  • 263,252
  • 30
  • 330
  • 514
O.O
  • 11,077
  • 18
  • 94
  • 182
  • How would you think you would ascertain that? I would go for the group, and see if the member is part of the group, rather than ask if the user is currently an administrator. Consider: http://stackoverflow.com/questions/3774072/how-can-i-get-all-users-in-a-local-group-with-good-performance also http://stackoverflow.com/questions/3212862/how-can-i-get-the-local-group-name-for-guests-administrators – jcolebrand Aug 02 '12 at 22:10
  • @jcolebrand - that's what this code is doing. Role = Group. "These roles represent the local Windows groups common to most installations of Windows NT, Windows 2000 and Windows XP." – O.O Aug 02 '12 at 22:20
  • Rephrasing the documentation, if you don't run as administrator, you aren't in the Administrators group, and the function doesn't lie. Could you provide some more details about why you wish to determine this? I ask because while I understand there are a few good reasons, there are also a lot of bad ones. –  Aug 02 '12 at 22:21
  • I read that as "I'm asking for the groups the user is in" not "I'm asking for the users in the group, and checking to see if the user is in the group". I think you're misunderstanding me. Don't ask what role the USER is in, ask what users are in the GROUP. Start from the other way around. Not everything can be solved from the perspective of the user, sometimes you take a hill by circling it and coming up the backside. – jcolebrand Aug 02 '12 at 22:22
  • @hvd - the app needs to run in read-only mode. Users with admin priv. can change values, others can only look at them. – O.O Aug 02 '12 at 22:24
  • What you're asking isn't to detect users with admin privileges, but to detect users that *don't* have admin privileges, but would be able to get them if prompted, and grant them admin privileges without prompting... Doesn't that somewhat bypass the point of UAC? –  Aug 02 '12 at 22:28
  • @hvd - Maybe you should ask that one as a separate question. lol. – O.O Aug 02 '12 at 22:38
  • @hvd no, because you can't read the administrative group if you don't have privileges, so you can't use that to bypass a security check. – jcolebrand Aug 02 '12 at 22:42

1 Answers1

4

Since I can't neatly post code in comments, like I can here, let me just suggest some pseudo code

var user = Windows.GetThisUser( me ); //current method (I said pseudo code)
function CheckIfImAdmin( user ) .... //current method

proposed method:

var administrativeUsers = Windows.GetUsersInRole( "admin" ); //use a SID here, much more reliable
foreach(user in administrativeUsers){
  if (user == me) return true;
  return false;
}

While this may look the same, it's not. Instead of querying the user to see if it's currently in a given role (non-escalated aren't) I'm focusing on who the administrators are and then asking if that group contains the user I want, namely the current user.

jcolebrand
  • 15,889
  • 12
  • 75
  • 121
  • I don't know enough about SIDS, but are they the same for windows 2000 SP4 through Windows 7? – O.O Aug 02 '12 at 22:29
  • Usually, and there's MSDN posts that list them, such as in the comment I left previous. – jcolebrand Aug 02 '12 at 22:39
  • OK. I'll have to research it more and come back, but I see what you are saying. – O.O Aug 02 '12 at 22:40
  • Note that this may still throw an error, and require the program to have been run as an administrator, so it's not something I've tried, just a suggestion of an attack vector. – jcolebrand Aug 02 '12 at 22:42
  • 1
    shouldn't the line 'return false;' be outside the foreach loop? – Mats Feb 04 '16 at 14:01