Check if logged on user is an administrator when non-elevated
Asked Answered
B

6

6

I needed to check whether the currently logged on user is an administrator however found that just using 'net localgroup administrators' was insufficient when it came to AD groups being a member of the administrators group.

[Edit:] It is easy to confuse administrator privilege in general with elevated privileges of a specific instance and I just want to highlight that this question/answer does not deal with process elevation status checking. The requirement is to generally ascertain whether or not a logged on user is an administrators group member. Much more common is the need to determine whether or not your script is running with administrator privileges. If this is what you require then please look here instead: Administrative privileges

In this particular case, there is a policy disabling the admin shares (ruling out a previous technique I used with Windows XP of testing for the existence of the admin share using \127.0.0.1\admin$ to determine if the current user is an administrator). [/Edit]

Below is the code I gathered and wrote see if the logged on user is an administrator.

I hope this helps someone else who requires the same thing that I did.

If anyone can provide a more elegant solution it would be appreciated!

Bemis answered 18/3, 2015 at 18:20 Comment(4)
Hope what helps? What's your question?Lelahleland
Hi Shaun, we're a question and answer site, and people are encouraged to answer their own questions when they know them. Can you re-phrase your initial post as a question, then post an answer?Knopp
Of course, elevation != member of local Administrators group. That is obvious. The real question is: Why do you need to determine if a user is a member of the local Administrators group but not check for elevation?Lelahleland
Then why did you see fit to provide that answer to my question 'Powershell - check if logged on user is an administrator'? Frustratingly my earlier reply to this has been edited out. I need my program to check whether the user is a local administrator and quit if so because the payload of the program is a forced logoff after a period of inactivity which must exclude administrators.Bemis
L
7

If you want to determine if the current user is a member of the local Administrators group (even if not elevated), here are some options.

$null -ne (whoami /groups /fo csv |
  ConvertFrom-Csv |
  Where-Object { $_.SID -eq "S-1-5-32-544" })

You can also use isadmin.exe (https://westmesatech.com/?page_id=23) and check for an exit code of 2 (member of administrators, but not enabled, hence not elevated).

Lelahleland answered 3/4, 2015 at 15:17 Comment(4)
I tested it using this:[string] $me = whoami /groups /fo csv | convertfrom-csv | where-object { $_.SID -eq "S-1-5-32-544" } If ($me.ToString().Contains("BUILTIN\Administrator")) { Write-Host "True"} Else {Write-Host "False"}Bemis
I don't understand why you think you need to cast to string or check for BUILTIN\Administrator. If that's the solution that "works," then it seems like you need to do a better job explaining the actual problem you're trying to solve.Lelahleland
Here's what I'm doing and it works fantastic, thanks! (whoami /groups /fo csv | convertfrom-csv | where-object SID -eq 'S-1-5-32-544' | select 'Group Name') -match 'admin' (returns true/false)Fairminded
You don't need the initial ( or trailing | Select 'Group Name') | -match 'admin' part (in fact, matching by string admin will fail when the local Administrators group doesn't contain that string, so I wouldn't recommend a string match). See my updated answer.Lelahleland
L
16

As noted, membership in the local Administrators group is not sufficient to determine if the current process is elevated. You can test for elevation in PowerShell like this:

$elevated = ([Security.Principal.WindowsPrincipal] `
 [Security.Principal.WindowsIdentity]::GetCurrent()
).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
Lelahleland answered 18/3, 2015 at 18:26 Comment(2)
As noted, user was trying to figure out if account is an administrator not if script is running elevated.Unmeasured
Understood, this answer addresses a different scenario, but it's good information for those who really do need to check for elevation (which is the actual question 99% of the time).Lelahleland
L
7

If you want to determine if the current user is a member of the local Administrators group (even if not elevated), here are some options.

$null -ne (whoami /groups /fo csv |
  ConvertFrom-Csv |
  Where-Object { $_.SID -eq "S-1-5-32-544" })

You can also use isadmin.exe (https://westmesatech.com/?page_id=23) and check for an exit code of 2 (member of administrators, but not enabled, hence not elevated).

Lelahleland answered 3/4, 2015 at 15:17 Comment(4)
I tested it using this:[string] $me = whoami /groups /fo csv | convertfrom-csv | where-object { $_.SID -eq "S-1-5-32-544" } If ($me.ToString().Contains("BUILTIN\Administrator")) { Write-Host "True"} Else {Write-Host "False"}Bemis
I don't understand why you think you need to cast to string or check for BUILTIN\Administrator. If that's the solution that "works," then it seems like you need to do a better job explaining the actual problem you're trying to solve.Lelahleland
Here's what I'm doing and it works fantastic, thanks! (whoami /groups /fo csv | convertfrom-csv | where-object SID -eq 'S-1-5-32-544' | select 'Group Name') -match 'admin' (returns true/false)Fairminded
You don't need the initial ( or trailing | Select 'Group Name') | -match 'admin' part (in fact, matching by string admin will fail when the local Administrators group doesn't contain that string, so I wouldn't recommend a string match). See my updated answer.Lelahleland
H
1

Using the SID:

([Security.Principal.WindowsIdentity]::GetCurrent().Groups | Select-String 'S-1-5-32-544')

Or using a "Well-known" security identifier name:

([Security.Principal.WindowsIdentity]::GetCurrent().Groups.IsWellKnown('BuiltinAdministratorsSid') -eq $true)

if you want to get all the SIDs and their names, please check this page: https://support.microsoft.com/en-us/help/243330/well-known-security-identifiers-in-windows-operating-systems

Hybrid answered 24/5, 2017 at 3:21 Comment(0)
R
1

By looking for BUILTIN\Administrators in whoami /all

$output = whoami /all
$IsAdministrator = $false

foreach($line in $output) {
  if ($line -like "*BUILTIN\Administrators*") {
      $IsAdministrator = $true
      break;
   } 
} 

if ($IsAdministrator)
{
    Write-Host "The Computer contains Adminstrator priveledges" -ForegroundColor Black -BackgroundColor Green
} else {
    Write-Host "The Computer does not have Adminstrator priveledges" -ForegroundColor -BackgroundColor Red
}
Romeyn answered 20/4, 2020 at 1:6 Comment(1)
This will fail when the group is not named Administrators (i.e., in non-English versions of Windows or if the group has been renamed). See my answer that uses the SID (S-1-5-32-544).Lelahleland
S
1

According to code from this blog, you can use this code, too:

# Get who I am
$Me = whoami.exe

# Get members of administrators group
$Admins = Get-LocalGroupMember -Name Administrators | 
          Select-Object -ExpandProperty name

# Check to see if this user is an administrator and act accordingly
if ($Admins -Contains $Me) {
  "$Me is a local administrator"
} 
else {
  "$Me is NOT a local administrator"
}
Selfconfidence answered 27/1, 2023 at 22:31 Comment(0)
B
-2

Thanks for the heads-up Bill - apologies, it was very late and I'm working 7-days/wk since Christmas.

Function IsCurrentUserAdmin( [String] $UserName )
# Returns true if current user in in the administrators group (directly or nested group) and false if not.
{
    $group = [ADSI] "WinNT://./Administrators,group" # https://mcmap.net/q/902866/-check-if-an-account-is-a-member-of-a-local-group-and-perform-an-if-else-in-powershell-2-0
    $members = @($group.psbase.Invoke("Members"))
    $AdminList = ($members | ForEach {$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)})
    If ($AdminList -contains $UserName) {
        Return $true
    } Else {
        # Adapted $LocalUsers from http://www.powertheshell.com/finding-local-user-accounts-in-powershell-3-0/
        $LocalUsers = net user | Select-Object -Skip 4 
        $LocalUsers = ($LocalUsers | Select-Object -First ($LocalUsers.Count - 2)).Trim()
        ForEach ($Item In $AdminList) {
            If (($LocalUsers.Contains($Item)) -eq $false) {
                # Lookup each AD group that is a member of the local administrators group and see if the current user is a member and return true if found
                If (([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole($Item) -eq $true) { Return $true }
            }
        }
        Return $false
    }
}

# Check if logged on user is an administrators group member and quit this program if so (to enable admins to manually install long-running software etc without logoff risk / disruption)

$UserName = ${Env:UserName}
[Bool] $AdminTest = IsCurrentUserAdmin $UserName
If ($AdminTest -eq $True) { 
    # Do something
} Else {
    # Do something else
}
Bemis answered 20/3, 2015 at 0:30 Comment(16)
That's an unnecessary amount of code to determine if the current user is elevated (see my answer).Lelahleland
Indeed you are correct Bill - however you have missed the point. Please re-read the question. Determining whether or not the current user session is elevated is out of scope for this article.Bemis
You do not need to enumerate the members of the Administrators group to determine if the current user is an administrator. Testing for elevation is all you need to do (see my answer). Aside from this, your code will fail anyway if the Administrators group is not named "Administrators".Lelahleland
'Testing for elevation is all you need to do (see my answer).' is incorrect I'm afraid. Let me explain my specific requirements as it will better help explain why I have now marked my successfully independently tested solution as the answer to the problem 'Powershell: check if logged on user is an administrator'; despite it being down-voted and accompanied by a non-working alternative solution. Let me explain why I cannot use your (process elevation status checking aspect of checking for administrator privileges) solution for my issue. It fails for the default use case in my scenario.Bemis
The Powershell program is to run on a Windows 7 x64 computer that has User Account Control (UAC) enabled that will be used by both users and administrators. If you are wondering why I need this it is because the wider requirement is for the program to forcibly log users off after a period of keyboard and mouse inactivity but not affect administrators.Bemis
It is frequently found that users "reserve" then leave a machine (that is against policy) by creating and running in Presentation Mode a Microsoft Powerpoint presentation with the message 'be right back or BRB' in a (usually successful until caught by staff) bid to prevent another users from making use of the machine. This technique also successfully prevents the GPO enforced screen-saver that forces logoff at 15 minutes of inactivity from running. The program needs to run after logon but quit if the user is an administrator.Bemis
Each minute the program monitors the time elapsed since the keyboard or mouse was last operated. The administrators will mostly be using domain accounts that are members of the Administrators group by virtue of a nested group membership of the Administrators local group. As a managed platform this name is guaranteed so I can safely make assumptions.Bemis
Nested group membership of the Administrators local group means that the administrators userID does not appear directly in the Administrators group. The program is running with UAC enabled but will not be running with elevated privileges. It is the process non-elevated privilege status that is reason why your proposed solution fails in my case and therefore cannot be marked as the correct answer to the question 'Powershell: check if logged on user is an administrator'.Bemis
A policy setting disabling the administrative shares exists (ruling out a previous technique I used in XP of testing for the existence of the admin share to determine if the current user is an administrator) so I had to look for a new solution. I couldn't find anything on the internet that could reliably detect if the logged on user is an administrator in this situation so had to resort to writing my own solution. This question was created to share my solution because as I say, I couldn't find anything else to do it.Bemis
I'm sure there are much more elegant solutions out there which is why I had intended to leave the question formally unanswered until now - but since you down-voted the only working proposed solution I felt the need to clarify the situation to make things right as they should be as mine is to date the only workable solution.Bemis
On your computer, when UAC is enabled and you are logged in with a domain user account that is a member of the administrators group by in-direct membership, please tell me Bill, when you run your solution inside a non-elevated powershell window, does it return that the user is an administrator? I ask because this scenario is critical as it represents the actual use case here and is therefore absolutely why you need to either undo the down-vote or leave it standing but only if accompanied with an alternative solution that actually works to 'check if logged on user is an administrator' in PoSh.Bemis
I cannot think of a more succint and accurate way to phrase the question. I have to make reference to the AD group side of things because this is the crux of the problem of checking if the logged on user is an administrator and I am confined to 150 characters in the title.Bemis
I think the source of confusion may be coming from the words chosen to make the call ..."IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator" as it implies that the check is for whether the user a member of the built in role "administrator". The reality though is that your proposal is susceptible to failure as a method to check that the logged on user is an administrator when UAC is enabled and the process is not elevated and I need the code to work in all UAC modes.Bemis
I appreciate the work you do for fellow users and don't want to appear ungrateful. I just need to set the record straight as I have failed to clarify from the outset that the code needs to work in all UAC modes for which I apologise for the inconvenience caused.Bemis
As a parting note, I just had a brainwave and figured that I can query gpresult /R more easily as that expands nested AD groups in its output. That ought to be more elegant than my first proposed solution! Right, I have some work to do!Bemis
If you are asking whether someone is a member (directly or indirectly) of the local Administrators group regardless of whether they're elevated, then rephrase and ask this specific question.Lelahleland

© 2022 - 2024 — McMap. All rights reserved.