使用PowerShell,如何向帐户授予"作为服务登录"的权限?

Jes*_*ert 18 powershell

我正在尝试使用powershell配置帐户凭据,但我需要授予帐户"作为服务登录"权限才能使其正常工作.我怎么能在PowerShell中做到这一点?

gre*_*ade 19

下面的PowerShell脚本将授予SeServiceLogonRight由指定的主机上计算机名由指定的用户(脚本就是从这里摘录:https://gist.github.com/grenade/8519655):

<#
.Synopsis
  Grant logon as a service right to the defined user.
.Parameter computerName
  Defines the name of the computer where the user right should be granted.
  Default is the local computer on which the script is run.
.Parameter username
  Defines the username under which the service should run.
  Use the form: domain\username.
  Default is the user under which the script is run.
.Example
  Usage:
  .\GrantSeServiceLogonRight.ps1 -computerName hostname.domain.com -username "domain\username"
#>
param(
  [string] $computerName = ("{0}.{1}" -f $env:COMPUTERNAME.ToLower(), $env:USERDNSDOMAIN.ToLower()),
  [string] $username = ("{0}\{1}" -f $env:USERDOMAIN, $env:USERNAME)
)
Invoke-Command -ComputerName $computerName -Script {
  param([string] $username)
  $tempPath = [System.IO.Path]::GetTempPath()
  $import = Join-Path -Path $tempPath -ChildPath "import.inf"
  if(Test-Path $import) { Remove-Item -Path $import -Force }
  $export = Join-Path -Path $tempPath -ChildPath "export.inf"
  if(Test-Path $export) { Remove-Item -Path $export -Force }
  $secedt = Join-Path -Path $tempPath -ChildPath "secedt.sdb"
  if(Test-Path $secedt) { Remove-Item -Path $secedt -Force }
  try {
    Write-Host ("Granting SeServiceLogonRight to user account: {0} on host: {1}." -f $username, $computerName)
    $sid = ((New-Object System.Security.Principal.NTAccount($username)).Translate([System.Security.Principal.SecurityIdentifier])).Value
    secedit /export /cfg $export
    $sids = (Select-String $export -Pattern "SeServiceLogonRight").Line
    foreach ($line in @("[Unicode]", "Unicode=yes", "[System Access]", "[Event Audit]", "[Registry Values]", "[Version]", "signature=`"`$CHICAGO$`"", "Revision=1", "[Profile Description]", "Description=GrantLogOnAsAService security template", "[Privilege Rights]", "$sids,*$sid")){
      Add-Content $import $line
    }
    secedit /import /db $secedt /cfg $import
    secedit /configure /db $secedt
    gpupdate /force
    Remove-Item -Path $import -Force
    Remove-Item -Path $export -Force
    Remove-Item -Path $secedt -Force
  } catch {
    Write-Host ("Failed to grant SeServiceLogonRight to user account: {0} on host: {1}." -f $username, $computerName)
    $error[0]
  }
} -ArgumentList $username
Run Code Online (Sandbox Code Playgroud)


kb4*_*000 10

这个函数很好地平衡了简洁和功能。在尝试授予用户权限之前,它会检查用户是否已经拥有该权限。

我尚未针对所有类型的特权对此进行测试,但它应该适用于大多数。

function Add-RightToUser([string] $Username, $Right) {
    $tmp = New-TemporaryFile

    $TempConfigFile = "$tmp.inf"
    $TempDbFile = "$tmp.sdb"

    Write-Host "Getting current policy"
    secedit /export /cfg $TempConfigFile

    $sid = ((New-Object System.Security.Principal.NTAccount($Username)).Translate([System.Security.Principal.SecurityIdentifier])).Value

    $currentConfig = Get-Content -Encoding ascii $TempConfigFile

    $newConfig = $null

    if ($currentConfig | Select-String -Pattern "^$Right = ") {
        if ($currentConfig | Select-String -Pattern "^$Right .*$sid.*$") {
            Write-Host "Already has right"
        }
        else {
            Write-Host "Adding $Right to $Username"

            $newConfig = $currentConfig -replace "^$Right .+", "`$0,*$sid"
        }
    }
    else {
        Write-Host "Right $Right did not exist in config. Adding $Right to $Username."

        $newConfig = $currentConfig -replace "^\[Privilege Rights\]$", "`$0`n$Right = *$sid"
    }

    if ($newConfig) {
        Set-Content -Path $TempConfigFile -Encoding ascii -Value $newConfig

        Write-Host "Validating configuration"
        $validationResult = secedit /validate $TempConfigFile

        if ($validationResult | Select-String '.*invalid.*') {
            throw $validationResult;
        }
        else {
            Write-Host "Validation Succeeded"
        }

        Write-Host "Importing new policy on temp database"
        secedit /import /cfg $TempConfigFile /db $TempDbFile

        Write-Host "Applying new policy to machine"
        secedit /configure /db $TempDbFile /cfg $TempConfigFile

        Write-Host "Updating policy"
        gpupdate /force

        Remove-Item $tmp* -ea 0
    }
}

#Example
Add-RightToUser -Username 'MyDomain\MyUser' -Right 'SeServiceLogonRight'
Run Code Online (Sandbox Code Playgroud)

移动

function Remove-RightFromUser([string] $Username, $Right) {
    $tmp = New-TemporaryFile

    $TempConfigFile = "$tmp.inf"
    $TempDbFile = "$tmp.sdb"

    Write-Host "Getting current policy"
    secedit /export /cfg $TempConfigFile

    $sid = ((New-Object System.Security.Principal.NTAccount($Username)).Translate([System.Security.Principal.SecurityIdentifier])).Value

    $currentConfig = Get-Content -Encoding ascii $TempConfigFile

    if ($currentConfig | Select-String -Pattern "^$Right .*$sid.*$") {
        Write-Host "Removing $Right from $Username"

        $newConfig = $currentConfig -replace "^($Right = .*?)(?>,\*$sid(.*?$)|\*$sid,(.*?$)|\*$sid$)", '$1$2$3'

        Set-Content -Path $TempConfigFile -Encoding ascii -Value $newConfig

        Write-Host "Validating configuration"
        $validationResult = secedit /validate $TempConfigFile

        if ($validationResult | Select-String '.*invalid.*') {
            throw $validationResult;
        }
        else {
            Write-Host "Validation Succeeded"
        }

        Write-Host "Importing new policy on temp database"
        secedit /import /cfg $TempConfigFile /db $TempDbFile

        Write-Host "Applying new policy to machine"
        secedit /configure /db $TempDbFile /cfg $TempConfigFile

        Write-Host "Updating policy"
        gpupdate /force

        Remove-Item $tmp* -ea 0
    }
    else {
        Write-Host "User $Username did not have right"
    }
}

#Example
Remove-RightFromUser -Username 'MyDomain\MyUser' -Right 'SeServiceLogonRight'
Run Code Online (Sandbox Code Playgroud)

  • 这对我有用。谢谢。现在我只想看看如何删除 SeServiceLogon 权限。 (2认同)
  • @JamesTSnell 我已经按照您的要求添加了一个删除示例。 (2认同)

Jup*_*aol 7

我是这样解决的:

基于:本文

你可以从这里下载

首先导入Carbon模块如下:

Import-Module -Name $Path_To_Carbon -Global -Prefix CA

[array]$UserPrivileges = Get-CAPrivileges -Identity $UserName;
[bool]$LogOnAsAServiceprivilegeFound = $false;

if ($UserPrivileges.Length > 0)
{
    if ($UserPrivileges -contains "SeServiceLogonRight")
    {
        $LogOnAsAServiceprivilegeFound = $true;
    }
}

if ($LogOnAsAServiceprivilegeFound -eq $false)
{
    Grant-CAPrivilege -Identity $UserName "SeServiceLogonRight"
}
Run Code Online (Sandbox Code Playgroud)

  • 无需检查现有权限。即使您多次调用它也能工作:Grant-CAPrivilege -Identity $UserName "SeServiceLogonRight" (2认同)

Bre*_*ane 7

有一个 Windows API 提供对本地安全策略AdvAPI32.dllLsa*方法的访问。

您可以利用 PowerShell 将 .NET 类型添加到当前会话的功能,以及 .NET 的 P/Invoke 来调用 Windows API,以便从 PowerShell 向用户授予“作为服务登录”权限。

作为一个最小的示例*,您首先需要向当前 PowerShell 会话添加一些新的 .NET 类型以使用 Windows API:

Add-Type @'
using System;
using System.Runtime.InteropServices;

public enum LSA_AccessPolicy : long
{
    // Other values omitted for clarity
    POLICY_ALL_ACCESS = 0x00001FFFL
}

[StructLayout(LayoutKind.Sequential)]
public struct LSA_UNICODE_STRING
{
    public UInt16 Length;
    public UInt16 MaximumLength;
    public IntPtr Buffer;
}

[StructLayout(LayoutKind.Sequential)]
public struct LSA_OBJECT_ATTRIBUTES
{
    public UInt32 Length;
    public IntPtr RootDirectory;
    public LSA_UNICODE_STRING ObjectName;
    public UInt32 Attributes;
    public IntPtr SecurityDescriptor;
    public IntPtr SecurityQualityOfService;
}

public static partial class AdvAPI32 {
    [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)]
    public static extern uint LsaOpenPolicy(
        ref LSA_UNICODE_STRING SystemName,
        ref LSA_OBJECT_ATTRIBUTES ObjectAttributes,
        uint DesiredAccess,
        out IntPtr PolicyHandle);

    [DllImport("advapi32.dll")]
    public static extern Int32 LsaClose(IntPtr ObjectHandle);

    [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)]
    public static extern uint LsaAddAccountRights(
        IntPtr PolicyHandle,
        byte[] AccountSid,
        LSA_UNICODE_STRING[] UserRights,
        uint CountOfRights);
}
'@
Run Code Online (Sandbox Code Playgroud)

然后,您需要打开本地安全策略的句柄:

function Get-LsaPolicyHandle() {
    $system = New-Object LSA_UNICODE_STRING
    $attrib = New-Object LSA_OBJECT_ATTRIBUTES -Property @{
        Length = 0
        RootDirectory = [System.IntPtr]::Zero
        Attributes = 0
        SecurityDescriptor = [System.IntPtr]::Zero
        SecurityQualityOfService = [System.IntPtr]::Zero
    };

    $handle = [System.IntPtr]::Zero

    $hr = [AdvAPI32]::LsaOpenPolicy([ref] $system, [ref]$attrib, [LSA_AccessPolicy]::POLICY_ALL_ACCESS, [ref]$handle)

    if (($hr -ne 0) -or ($handle -eq [System.IntPtr]::Zero)) {
        Write-Error "Failed to open Local Security Authority policy. Error code: $hr"
    } else {
        $handle
    }
}
Run Code Online (Sandbox Code Playgroud)

要添加新权限,您首先需要创建一个新权限:

function New-Right([string]$rightName){
    $unicodeCharSize = 2
    New-Object LSA_UNICODE_STRING -Property @{
        Buffer = [System.Runtime.InteropServices.Marshal]::StringToHGlobalUni($rightName)
        Length = $rightName.Length * $unicodeCharSize
        MaximumLength = ($rightName.Length + 1) * $unicodeCharSize
    }
}
Run Code Online (Sandbox Code Playgroud)

然后您可以将该权限添加到安全策略中:

function Grant-Rights([System.IntPtr]$policyHandle, [byte[]]$sid, [LSA_UNICODE_STRING[]]$rights) {
    $result = [AdvAPI32]::LsaAddAccountRights($policyHandle, $sid, $rights, 1)
    if ($result -ne 0) {
        Write-Error "Failed to grant right. Error code $result"
    } 
}
Run Code Online (Sandbox Code Playgroud)

因此,将它们放在一起,您就可以使用这些函数:

function Grant-LogonAsServiceRight([byte[]]$sid) { 
    $logonAsServiceRightName = "SeServiceLogonRight"

    try {
        $policy = Get-LsaPolicyHandle
        $right = New-Right $logonAsServiceRightName
        Grant-Rights $policy $sid @($right)
    }
    finally {
        if($null -ne $policy){
            [AdvAPI32]::LsaClose($policy) | Out-Null
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

还有其他方法可以AdvAPI32枚举用户的帐户权限、删除权限等。

--

*我按照Azure DevOps Pipeline Agent 存储库中的代码来了解如何使用AdvAPI32.


Don*_*nes 5

您也可以在PSH中执行此链接。http://www.derkeiler.com/Newsgroups/microsoft.public.windowsxp.security_admin/2003-12/2865.html

问题在于,实际上没有任何公共API可以管理这些设置,因此使用ResKits中提供的命令行工具会使您有些困惑。

  • 谢谢。我最终使用ntrights来做到这一点。ntrights.exe + r SeServiceLogonRight -u &lt;用户名/组名&gt; http://support.microsoft.com/?kbid=279664 (2认同)

Luk*_*uke 5

这不是纯粹的 PowerShell,但至少您不需要第三方工具。
一切都已经在您的计算机上,并且可以从命令行运行。

#Requires -RunAsAdministrator

#The SID you want to add
$AccountSid = 'S-1-5-21-1234567890-1234567890-123456789-500'

$ExportFile = 'c:\temp\CurrentConfig.inf'
$SecDb = 'c:\temp\secedt.sdb'
$ImportFile = 'c:\temp\NewConfig.inf'

#Export the current configuration
secedit /export /cfg $ExportFile

#Find the current list of SIDs having already this right
$CurrentServiceLogonRight = Get-Content -Path $ExportFile |
    Where-Object -FilterScript {$PSItem -match 'SeServiceLogonRight'}

#Create a new configuration file and add the new SID
$FileContent = @'
[Unicode]
Unicode=yes
[System Access]
[Event Audit]
[Registry Values]
[Version]
signature="$CHICAGO$"
Revision=1
[Profile Description]
Description=GrantLogOnAsAService security template
[Privilege Rights]
{0}*{1}
'@ -f $(
        if($CurrentServiceLogonRight){"$CurrentServiceLogonRight,"}
        else{'SeServiceLogonRight = '}
    ), $AccountSid

Set-Content -Path $ImportFile -Value $FileContent

#Import the new configuration 
secedit /import /db $SecDb /cfg $ImportFile
secedit /configure /db $SecDb
Run Code Online (Sandbox Code Playgroud)


小智 5

使用碳!上面的一些建议已经过时了,以下是对我有用的建议:

(在具有提升权限的 powershell 中)

Install-Module -Name 'Carbon' -AllowClobber
Import-Module 'Carbon'
$Identity = "<username>"
$privilege = "SeServiceLogonRight"
$CarbonDllPath = "C:\Program Files\WindowsPowerShell\Modules\Carbon\2.10.2\bin\fullclr\Carbon.dll"
[Reflection.Assembly]::LoadFile($CarbonDllPath)
[Carbon.Security.Privilege]::GrantPrivileges($Identity, $privilege)
Run Code Online (Sandbox Code Playgroud)

  • 根据您的 PowerShell 版本,模块可能会安装在其他地方,而我使用 `$CarbonDllPath = "$((Get-Module -name 'Carbon').Path | Split-Path)\bin\fullclr\Carbon.dll"`动态设置 DllPath。 (2认同)