Checking for an elevated PowerShell prompt
I just built a tool for a team of consultants to use, and some of the commands require elevation. Rather than relying on telling them it needs to be elevated, I wanted to be able to exit immediately if the session wasn't so precious time wasn't wasted.
First, we need to figure out who the user is. To do that, you can use the [System.Security.Principal.WindowsIdentity]::GetCurrent() method and save it to a variable.
$WindowsIdentity = [System.Security.Principal.Windowsidentity]::GetCurrent()
If you're curious about what's inside, check it out:
PS C:\> $WindowsIdentity
AuthenticationType : Kerberos
ImpersonationLevel : None
IsAuthenticated : True
IsGuest : False
IsSystem : False
IsAnonymous : False
Name : NORTHAMERICA\aaguilme
Owner : S-1-5-21-124525095-708259637-1543119021-1436192
User : S-1-5-21-124525095-708259637-1543119021-1436192
Groups : {S-1-5-21-124525095-708259637-1543119021-513, S-1-1-0, S-1-5-32-559, S-1-5-32-545...}
Token : 2564
AccessToken : Microsoft.Win32.SafeHandles.SafeAccessTokenHandle
UserClaims : {https://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: NORTHAMERICA\aaguilme,
https://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid:
S-1-5-21-124525095-708259637-1543119021-1436192,
https://schemas.microsoft.com/ws/2008/06/identity/claims/primarygroupsid:
S-1-5-21-124525095-708259637-1543119021-513,
https://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid:
S-1-5-21-124525095-708259637-1543119021-513...}
DeviceClaims : {}
Claims : {https://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: NORTHAMERICA\aaguilme,
https://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid:
S-1-5-21-124525095-708259637-1543119021-1436192,
https://schemas.microsoft.com/ws/2008/06/identity/claims/primarygroupsid:
S-1-5-21-124525095-708259637-1543119021-513,
https://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid:
S-1-5-21-124525095-708259637-1543119021-513...}
Actor :
BootstrapContext :
Label :
NameClaimType : https://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
RoleClaimType : https://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid
PS C:\> $WindowsIdentity | gm
TypeName: System.Security.Principal.WindowsIdentity
Name MemberType Definition
---- ---------- ----------
AddClaim Method void AddClaim(System.Security.Claims.Claim claim)
AddClaims Method void AddClaims(System.Collections.Generic.IEnumerable[System.Security.Claims.Claim] cl...
Clone Method System.Security.Claims.ClaimsIdentity Clone()
Dispose Method void Dispose(), void IDisposable.Dispose()
Equals Method bool Equals(System.Object obj)
FindAll Method System.Collections.Generic.IEnumerable[System.Security.Claims.Claim] FindAll(System.Pr...
FindFirst Method System.Security.Claims.Claim FindFirst(System.Predicate[System.Security.Claims.Claim] ...
GetHashCode Method int GetHashCode()
GetObjectData Method void ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, ...
GetType Method type GetType()
HasClaim Method bool HasClaim(System.Predicate[System.Security.Claims.Claim] match), bool HasClaim(str...
Impersonate Method System.Security.Principal.WindowsImpersonationContext Impersonate()
OnDeserialization Method void IDeserializationCallback.OnDeserialization(System.Object sender)
RemoveClaim Method void RemoveClaim(System.Security.Claims.Claim claim)
ToString Method string ToString()
TryRemoveClaim Method bool TryRemoveClaim(System.Security.Claims.Claim claim)
WriteTo Method void WriteTo(System.IO.BinaryWriter writer)
AccessToken Property Microsoft.Win32.SafeHandles.SafeAccessTokenHandle AccessToken {get;}
Actor Property System.Security.Claims.ClaimsIdentity Actor {get;set;}
AuthenticationType Property string AuthenticationType {get;}
BootstrapContext Property System.Object BootstrapContext {get;set;}
Claims Property System.Collections.Generic.IEnumerable[System.Security.Claims.Claim] Claims {get;}
DeviceClaims Property System.Collections.Generic.IEnumerable[System.Security.Claims.Claim] DeviceClaims {get;}
Groups Property System.Security.Principal.IdentityReferenceCollection Groups {get;}
ImpersonationLevel Property System.Security.Principal.TokenImpersonationLevel ImpersonationLevel {get;}
IsAnonymous Property bool IsAnonymous {get;}
IsAuthenticated Property bool IsAuthenticated {get;}
IsGuest Property bool IsGuest {get;}
IsSystem Property bool IsSystem {get;}
Label Property string Label {get;set;}
Name Property string Name {get;}
NameClaimType Property string NameClaimType {get;}
Owner Property System.Security.Principal.SecurityIdentifier Owner {get;}
RoleClaimType Property string RoleClaimType {get;}
Token Property System.IntPtr Token {get;}
User Property System.Security.Principal.SecurityIdentifier User {get;}
UserClaims Property System.Collections.Generic.IEnumerable[System.Security.Claims.Claim] UserClaims {get;}
Now, we need to instantiate a new Windows Security Principal object using the identity we just created as its argument. This object is necessary because it exposes the IsInRole method.
$Principal = New-Object System.Security.Principal.WindowsPrincipal($WindowsIdentity)
Again, we can explore what's inside:
PS C:\> $Principal
Identity : System.Security.Principal.WindowsIdentity
UserClaims : {https://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: NORTHAMERICA\aaguilme,
https://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid:
S-1-5-21-124525095-708259637-1543119021-1436192,
https://schemas.microsoft.com/ws/2008/06/identity/claims/primarygroupsid:
S-1-5-21-124525095-708259637-1543119021-513,
https://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid:
S-1-5-21-124525095-708259637-1543119021-513...}
DeviceClaims : {}
Claims : {https://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: NORTHAMERICA\aaguilme,
https://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid:
S-1-5-21-124525095-708259637-1543119021-1436192,
https://schemas.microsoft.com/ws/2008/06/identity/claims/primarygroupsid:
S-1-5-21-124525095-708259637-1543119021-513,
https://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid:
S-1-5-21-124525095-708259637-1543119021-513...}
Identities : {NORTHAMERICA\aaguilme}
PS C:\windows\system32> $Principal | gm
TypeName: System.Security.Principal.WindowsPrincipal
Name MemberType Definition
---- ---------- ----------
AddIdentities Method void AddIdentities(System.Collections.Generic.IEnumerable[System.Security.Claims.ClaimsIden...
AddIdentity Method void AddIdentity(System.Security.Claims.ClaimsIdentity identity)
Clone Method System.Security.Claims.ClaimsPrincipal Clone()
Equals Method bool Equals(System.Object obj)
FindAll Method System.Collections.Generic.IEnumerable[System.Security.Claims.Claim] FindAll(System.Predica...
FindFirst Method System.Security.Claims.Claim FindFirst(System.Predicate[System.Security.Claims.Claim] match...
GetHashCode Method int GetHashCode()
GetType Method type GetType()
HasClaim Method bool HasClaim(System.Predicate[System.Security.Claims.Claim] match), bool HasClaim(string t...
IsInRole Method bool IsInRole(string role), bool IsInRole(System.Security.Principal.WindowsBuiltInRole role...
ToString Method string ToString()
WriteTo Method void WriteTo(System.IO.BinaryWriter writer)
Claims Property System.Collections.Generic.IEnumerable[System.Security.Claims.Claim] Claims {get;}
DeviceClaims Property System.Collections.Generic.IEnumerable[System.Security.Claims.Claim] DeviceClaims {get;}
Identities Property System.Collections.Generic.IEnumerable[System.Security.Claims.ClaimsIdentity] Identities {g...
Identity Property System.Security.Principal.IIdentity Identity {get;}
UserClaims Property System.Collections.Generic.IEnumerable[System.Security.Claims.Claim] UserClaims {get;}
Like I previously mentioned, the IsInRole method is the one we're interested in, since we're trying to see if the user is running the PowerShell prompt as the Administrator Role. You can see the valid roles here (https://msdn.microsoft.com/en-us/library/system.security.principal.windowsbuiltinrole(v=vs.110).aspx).
From here, the final step is to query whether or not the user is executing using the "Administrator" role. To check that, you can either build a variable for the built-in administrator role or just pass the string "Administrator."
$AdminRole = [System.Security.Principal.WindowsBuiltInRole]::Administrator
$Principal.IsInRole("Administrator")
$Principal.IsInRole($AdminRole)
The result is the same when you query....sometimes. I've found that passing the string "Administrator" when the session is elevated will result in an error, while passing a string when the session is *not* elevated will return a Boolean. Passing the object created by [System.Security.Principal.WindowsBuiltInRole] always returns the correct value, so that's what I'd recommend using.
PS C:\> $Principal.IsInRole($AdminRole)
True
# Check if Elevated
$WindowsIdentity = [system.security.principal.windowsidentity]::GetCurrent()
$Principal = New-Object System.Security.Principal.WindowsPrincipal($WindowsIdentity)
$AdminRole = [System.Security.Principal.WindowsBuiltInRole]::Administrator
if ($Principal.IsInRole($AdminRole))
{
Write-Host -ForegroundColor Green "Elevated PowerShell session detected. Continuing."
}
else
{
Write-Host -ForegroundColor Red "This application/script must be run in an elevated PowerShell window. Please launch an elevated session and try again."
Break
}
Comments
- Anonymous
November 28, 2016
Thanks - Anonymous
February 18, 2018
thank you for this article - Anonymous
July 27, 2018
(The content was deleted per user request)