要查詢有哪些帳號或群組可以登入 Windows 本機操作,最簡單的做法是使用「本機安全性原則」查詢「使用者權限指派/允許本機登入」,而所謂「允許本機登入」對映的是名為 SeInteractiveLogonRight 的 Windows 使用者權限。延伸閱讀:使用 PowerShell 設定使用者權限(User Right)

如果嫌開 UI 太麻煩太繁瑣,想透過指令快速查詢或將結果轉存成檔案呢?可以使用 Sysinternals 超級工具包的 AccessChk

如果因為環境特殊,不便下載或部署第三方工具,要怎麼用 PowerShell 完成?

我用 80 行 PowerShell 寫了一個取代 AccessChk 的使用者權限查詢功能:(註:secedit /export 需管理者權限,程式有用到自動改用管理者權限執行 .ps1 的小技巧)

param (
    [string]$Right,
    [switch]$Expand
)
$ErrorActionPreference = 'STOP'
function ListRights($right, $expand) {
    # Call secedit to get the list of rights
    $tmpPath = [System.IO.Path]::GetTempFileName()
    secedit.exe /export /cfg $tmpPath | Out-Null
    $raw = Get-Content $tmpPath 
    Remove-Item $tmpPath
    $rights = @{}
    $inZone = $false
    $raw | ForEach-Object {
        if ($inZone) {
            if ($_ -match '^\s*(\S+)\s*=\s*(\S+)\s*$') {
                $rightName = $matches[1]
                $rights[$rightName] = @()
                $matches[2].Split(',') | ForEach-Object {
                    try {
                        $name = $_
                        if ($name -match '^\*') {
                            $sid = New-Object System.Security.Principal.SecurityIdentifier($name.Trim('*'))
                            $name = $sid.Translate([System.Security.Principal.NTAccount]).Value
                        }
                    }
                    catch {
                        Write-Host "Failed to translate $_" -ForegroundColor Red
                    }
                    $rights[$rightName] += $name
                }
            }
            elseif ($_ -match '^\[') {
                $inZone = $false
            }
        }
        elseif ($_ -eq '[Privilege Rights]') {
            $inZone = $true
        }
    }
    if ($right) {
        Write-Host $right
        Write-Host ('-' * 60)
        if ($expand) {
            $localGroupMembers = @{} 
            Get-LocalGroup | ForEach-Object {
                $sid = New-Object System.Security.Principal.SecurityIdentifier($_.Sid)
                $acnt = $sid.Translate([System.Security.Principal.NTAccount]).Value
                $localGroupMembers[$acnt] = Get-LocalGroupMember $_ | Select-Object -ExpandProperty Name
            }
            $rights[$right] | ForEach-Object {
                Write-Host $_
                $grpName = $_
                if ($localGroupMembers.ContainsKey($grpName)) {
                    $localGroupMembers[$grpName] | ForEach-Object {
                        Write-Host "  - $_"
                    }
                }
                else {
                    Write-Host "  (No members)"
                }
            }
        }
        else {
            $rights[$right]
        }
    }
    else {
        $rights
    }
}
$wp = [Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()
if (-Not $wp.IsInRole([Security.Principal.WindowsBuiltInRole]"Administrator")) {
    $rawCmd = $MyInvocation.Line
    $rawArgs = $rawCmd.Substring($rawCmd.IndexOf('.ps1') + 4)
	if ($rawCmd.StartsWith('if')) { $rawArgs = '' }
    Start-Process Powershell -Verb RunAs -ArgumentList "$PSCommandPath $rawArgs" 
}
else {
    ListRights $Right $Expand
}

共三種用法:

PSAccessChk.ps1 SeInteractiveLogonRight # 查本機登入權限對象
PSAccessChk.ps1 SeInteractiveLogonRight -Expand # 查本機登入權限對象並展開本機群組成員
PSAccessChk.ps1 # 列出全部權限及其授與對象

To check which accounts or groups can log into a Windows machine, the simplest method is to use the “Local Security Policy” to query “User Rights Assignment/Allow log on locally.” For a quicker command-based method, you can use the Sysinternals tool AccessChk. Alternatively, if third-party tools are not an option, an 80-line PowerShell script can be used to perform the same function, listing and expanding user rights and group members.


Comments

Be the first to post a comment

Post a comment