Public/Remove-WindowsRight.ps1
# Copyright: (c) 2018, Jordan Borean (@jborean93) <jborean93@gmail.com> # MIT License (see LICENSE or https://opensource.org/licenses/MIT) Function Remove-WindowsRight { <# .SYNOPSIS Remove an account from the privilege/right membership on the host specified. .DESCRIPTION This cmdlet will run on localhost by default but a remote host can be specified. This requires administrative privileges to run. .PARAMETER Name [String[]] Privilege(s) or Right(s) to remove the account from. See https://docs.microsoft.com/en-us/windows/desktop/SecAuthZ/privilege-constants for a list of valid privilege constants and https://docs.microsoft.com/en-us/windows/desktop/SecAuthZ/account-rights-constants for a list of valid account rights. .PARAMETER Account [System.Security.Principal.IdentityReference[]] Remove the accounts specified from the privilege/right. .PARAMETER ComputerName [String] The host to remove the accounts from, if not set then this will run on the localhost. This uses the current user's credentials to authenticate with the remote host. .INPUTS [String] The privilege/right name(s) to remove the accounts from. .EXAMPLE $admin_sid = New-Object -TypeName System.Security.Principal.SecurityIdentifier -ArgumentList "S-1-5-32-544" $user_sid = New-Object -TypeName System.Security.Principal.SecurityIdentifier -ArgumentList "S-1-5-32-545" # remove a privilege from a single account Remove-WindowsRight -Name SeDebugPrivilege -Account $admin_sid # remove a privilege from multiple accounts Remove-WindowsRight -Name SeInteractiveLogonRight -Account $admin_sid, $user_sid # remove multiple privileges from a single account Remove-WindowsRight -Name SeDebugPrivilege, SeInteractiveLogonRight -Account $admin_sid # remove multiple privileges from multiple accounts Remove-WindowsRight -Name SeDebugPrivilege, SeInteractiveLogonRight -Account $admin_sid, $user_sid # remove a privilege from an account on a remote host Remove-WindowsRight -Name SeDebugPrivilege -Account $admin_sid -ComputerName server-remote .NOTES This cmdlets opens up the LSA policy object with the POLICY_LOOKUP_NAMES, and POLICY_VIEW_LOCAL_INFORMATION access rights. This will fail if the current user does not have these access rights. #> [CmdletBinding(SupportsShouldProcess=$true)] param( [Parameter(Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true)][String[]]$Name, [Parameter(Position=1, Mandatory=$true)][System.Security.Principal.IdentityReference[]]$Account, [Parameter(Position=2)][String]$ComputerName ) Begin { $policy = Open-LsaPolicy -AccessMask "LookupNames, ViewLocalInformation" -ComputerName $ComputerName $actual_membership = @{} $remove_members = [String[]]@($Account | ForEach-Object { $_.Translate([System.Security.Principal.SecurityIdentifier]).ToString() }) } Process { foreach ($right in $Name) { Write-Verbose -Message "Getting current membership for the privilege/right '$right'" try { $actual_members = [String[]]@([PSPrivilege.Lsa]::EnumerateAccountsWithUserRight($policy, $right) | ForEach-Object { $_.ToString() }) } catch [ArgumentException] { Write-Error -Message "Invalid privilege or right name '$right'" -Category InvalidArgument continue } $accounts_to_remove = [String[]]@([Linq.Enumerable]::Intersect($remove_members, $actual_members)) $actual_membership.$right = $accounts_to_remove } } End { foreach ($acct in $Account) { $sid = $acct.Translate([System.Security.Principal.SecurityIdentifier]).ToString() $rights = ($actual_membership.GetEnumerator() | Where-Object { $_.Value.Contains($sid) }).Name if ($rights.Count -gt 0) { Write-Verbose -Message "Removing privileges/rights for the account '$sid'" if ($PSCmdlet.ShouldProcess($sid, "Remove the account rights $($rights -join ", ")")) { [PSPrivilege.Lsa]::RemoveAccountRights($policy, $acct, $rights) } } else { Write-Verbose -Message "No action required for account '$sid'" } } Write-Verbose -Message "Closing opened LSA policy" $policy.Dispose() } } |