使用 Powershell 为域组设置文件夹权限时收到 "Incorrectly ordered" 错误消息
Getting "Incorrectly ordered" error message when setting a folder permission to a domain group using Powershell
我正在尝试通过 Powershell 为文件夹设置权限以下是代码:
$acl = Get-Acl $folderPath
$acl.SetAccessRuleProtection($True, $True)
$ruleOwner = New-Object System.Security.AccessControl.FileSystemAccessRule($group,"Modify", "ContainerInherit, ObjectInherit", "None", "Allow")
$acl.AddAccessRule($ruleOwner)
Set-Acl $folderPath $acl
一旦我 运行 此代码并尝试打开相关文件夹的安全选项卡,我收到错误消息:
The permissions on [folder name] are incorrectly ordered, which may cause some entries to be ineffective.
将文件夹权限设置为特定组的正确方法是什么?
访问规则 (ACE) 需要 ordered in a certain way 在 ACL 中。
基本上顺序是
- 所有显式 ACE 都放在一个组中,位于任何继承的 ACE 之前。
- 在显式 ACE 组中,拒绝访问的 ACE 位于允许访问的 ACE 之前。
- 继承的 ACE 按照继承顺序排列。从子对象的父对象继承的 ACE 先出现,然后是从祖父对象继承的 ACE,依此类推对象树。
- 对于每个级别的继承 ACE,拒绝访问的 ACE 位于允许访问的 ACE 之前。
如果此顺序以某种方式混淆,您将看到“权限顺序不正确”错误消息。
要重新排列权限的顺序,您可以使用以下函数:
function Repair-DirectoryPermissions {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
[ValidateScript({Test-Path $_ -PathType Container})]
[string]$Path
)
$acl = Get-Acl -Path $Path
# create a new empty ACL object
$newAcl = New-Object System.Security.AccessControl.DirectorySecurity
# copy the access rules from the existing ACL to the new one in the correct order
# first the explicit DENY rules
$acl.Access | Where-Object { !$_.IsInherited -and $_.AccessControlType -eq 'Deny' } | ForEach-Object {
$newAcl.AddAccessRule($_)
}
# next the explicit ALLOW rules
$acl.Access | Where-Object { !$_.IsInherited -and $_.AccessControlType -eq 'Allow' } | ForEach-Object {
$newAcl.AddAccessRule($_)
}
# finally the inherited rules
$acl.Access | Where-Object { $_.IsInherited } | ForEach-Object {
$newAcl.AddAccessRule($_)
}
# set the the reordered ACL to the directory object
Set-Acl -Path $Path -AclObject $newAcl
}
并像这样使用它:
Repair-DirectoryPermissions -Path 'D:\Blah'
执行此操作时,您可能会遇到异常,告诉您需要 SeSecurityPrivilege
权限才能执行此操作。
为此,在脚本之上添加另一个函数:
function Enable-Privilege {
[CmdletBinding(ConfirmImpact = 'low', SupportsShouldProcess = $false)]
[OutputType('System.Boolean')]
Param(
[Parameter(Mandatory = $true, Position = 0)]
[ValidateSet(
"SeAssignPrimaryTokenPrivilege", "SeAuditPrivilege", "SeBackupPrivilege", "SeChangeNotifyPrivilege",
"SeCreateGlobalPrivilege", "SeCreatePagefilePrivilege", "SeCreatePermanentPrivilege",
"SeCreateSymbolicLinkPrivilege", "SeCreateTokenPrivilege", "SeDebugPrivilege", "SeEnableDelegationPrivilege",
"SeImpersonatePrivilege", "SeIncreaseBasePriorityPrivilege", "SeIncreaseQuotaPrivilege",
"SeIncreaseWorkingSetPrivilege", "SeLoadDriverPrivilege", "SeLockMemoryPrivilege",
"SeMachineAccountPrivilege", "SeManageVolumePrivilege", "SeProfileSingleProcessPrivilege",
"SeRelabelPrivilege", "SeRemoteShutdownPrivilege", "SeRestorePrivilege", "SeSecurityPrivilege",
"SeShutdownPrivilege", "SeSyncAgentPrivilege", "SeSystemEnvironmentPrivilege", "SeSystemProfilePrivilege",
"SeSystemtimePrivilege", "SeTakeOwnershipPrivilege", "SeTcbPrivilege", "SeTimeZonePrivilege",
"SeTrustedCredManAccessPrivilege", "SeUndockPrivilege", "SeUnsolicitedInputPrivilege")]
[String]$Privilege,
[Parameter(Position = 1)]
$ProcessId = $PID,
[switch]$Disable
)
begin {
Add-Type -TypeDefinition @'
using System;
using System.Runtime.InteropServices;
public class Privilege {
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);
[DllImport("advapi32.dll", SetLastError = true)]
internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct TokPriv1Luid {
public int Count;
public long Luid;
public int Attr;
}
internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
internal const int SE_PRIVILEGE_DISABLED = 0x00000000;
internal const int TOKEN_QUERY = 0x00000008;
internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
public static bool EnablePrivilege(long processHandle, string privilege, bool disable) {
bool retVal;
TokPriv1Luid tp;
IntPtr hproc = new IntPtr(processHandle);
IntPtr htok = IntPtr.Zero;
retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
tp.Count = 1;
tp.Luid = 0;
if(disable) { tp.Attr = SE_PRIVILEGE_DISABLED; }
else { tp.Attr = SE_PRIVILEGE_ENABLED; }
retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid);
retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
return retVal;
}
}
'@
}
process {
try {
$proc = Get-Process -Id $ProcessId -ErrorAction Stop
$name = $proc.ProcessName
$handle = $proc.Handle
$action = if ($Disable) { 'Disabling' } else { 'Enabling' }
Write-Verbose ("{0} '{1}' for process {2}" -f $action, $Privilege, $name)
[Privilege]::EnablePrivilege($handle, $Privilege, [bool]$Disable)
}
catch {
throw
}
}
}
并调用两个函数:
Enable-Privilege -Privilege SeSecurityPrivilege
Repair-DirectoryPermissions -Path 'D:\Blah'
我正在尝试通过 Powershell 为文件夹设置权限以下是代码:
$acl = Get-Acl $folderPath
$acl.SetAccessRuleProtection($True, $True)
$ruleOwner = New-Object System.Security.AccessControl.FileSystemAccessRule($group,"Modify", "ContainerInherit, ObjectInherit", "None", "Allow")
$acl.AddAccessRule($ruleOwner)
Set-Acl $folderPath $acl
一旦我 运行 此代码并尝试打开相关文件夹的安全选项卡,我收到错误消息:
The permissions on [folder name] are incorrectly ordered, which may cause some entries to be ineffective.
将文件夹权限设置为特定组的正确方法是什么?
访问规则 (ACE) 需要 ordered in a certain way 在 ACL 中。 基本上顺序是
- 所有显式 ACE 都放在一个组中,位于任何继承的 ACE 之前。
- 在显式 ACE 组中,拒绝访问的 ACE 位于允许访问的 ACE 之前。
- 继承的 ACE 按照继承顺序排列。从子对象的父对象继承的 ACE 先出现,然后是从祖父对象继承的 ACE,依此类推对象树。
- 对于每个级别的继承 ACE,拒绝访问的 ACE 位于允许访问的 ACE 之前。
如果此顺序以某种方式混淆,您将看到“权限顺序不正确”错误消息。
要重新排列权限的顺序,您可以使用以下函数:
function Repair-DirectoryPermissions {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
[ValidateScript({Test-Path $_ -PathType Container})]
[string]$Path
)
$acl = Get-Acl -Path $Path
# create a new empty ACL object
$newAcl = New-Object System.Security.AccessControl.DirectorySecurity
# copy the access rules from the existing ACL to the new one in the correct order
# first the explicit DENY rules
$acl.Access | Where-Object { !$_.IsInherited -and $_.AccessControlType -eq 'Deny' } | ForEach-Object {
$newAcl.AddAccessRule($_)
}
# next the explicit ALLOW rules
$acl.Access | Where-Object { !$_.IsInherited -and $_.AccessControlType -eq 'Allow' } | ForEach-Object {
$newAcl.AddAccessRule($_)
}
# finally the inherited rules
$acl.Access | Where-Object { $_.IsInherited } | ForEach-Object {
$newAcl.AddAccessRule($_)
}
# set the the reordered ACL to the directory object
Set-Acl -Path $Path -AclObject $newAcl
}
并像这样使用它:
Repair-DirectoryPermissions -Path 'D:\Blah'
执行此操作时,您可能会遇到异常,告诉您需要 SeSecurityPrivilege
权限才能执行此操作。
为此,在脚本之上添加另一个函数:
function Enable-Privilege {
[CmdletBinding(ConfirmImpact = 'low', SupportsShouldProcess = $false)]
[OutputType('System.Boolean')]
Param(
[Parameter(Mandatory = $true, Position = 0)]
[ValidateSet(
"SeAssignPrimaryTokenPrivilege", "SeAuditPrivilege", "SeBackupPrivilege", "SeChangeNotifyPrivilege",
"SeCreateGlobalPrivilege", "SeCreatePagefilePrivilege", "SeCreatePermanentPrivilege",
"SeCreateSymbolicLinkPrivilege", "SeCreateTokenPrivilege", "SeDebugPrivilege", "SeEnableDelegationPrivilege",
"SeImpersonatePrivilege", "SeIncreaseBasePriorityPrivilege", "SeIncreaseQuotaPrivilege",
"SeIncreaseWorkingSetPrivilege", "SeLoadDriverPrivilege", "SeLockMemoryPrivilege",
"SeMachineAccountPrivilege", "SeManageVolumePrivilege", "SeProfileSingleProcessPrivilege",
"SeRelabelPrivilege", "SeRemoteShutdownPrivilege", "SeRestorePrivilege", "SeSecurityPrivilege",
"SeShutdownPrivilege", "SeSyncAgentPrivilege", "SeSystemEnvironmentPrivilege", "SeSystemProfilePrivilege",
"SeSystemtimePrivilege", "SeTakeOwnershipPrivilege", "SeTcbPrivilege", "SeTimeZonePrivilege",
"SeTrustedCredManAccessPrivilege", "SeUndockPrivilege", "SeUnsolicitedInputPrivilege")]
[String]$Privilege,
[Parameter(Position = 1)]
$ProcessId = $PID,
[switch]$Disable
)
begin {
Add-Type -TypeDefinition @'
using System;
using System.Runtime.InteropServices;
public class Privilege {
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);
[DllImport("advapi32.dll", SetLastError = true)]
internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct TokPriv1Luid {
public int Count;
public long Luid;
public int Attr;
}
internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
internal const int SE_PRIVILEGE_DISABLED = 0x00000000;
internal const int TOKEN_QUERY = 0x00000008;
internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
public static bool EnablePrivilege(long processHandle, string privilege, bool disable) {
bool retVal;
TokPriv1Luid tp;
IntPtr hproc = new IntPtr(processHandle);
IntPtr htok = IntPtr.Zero;
retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
tp.Count = 1;
tp.Luid = 0;
if(disable) { tp.Attr = SE_PRIVILEGE_DISABLED; }
else { tp.Attr = SE_PRIVILEGE_ENABLED; }
retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid);
retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
return retVal;
}
}
'@
}
process {
try {
$proc = Get-Process -Id $ProcessId -ErrorAction Stop
$name = $proc.ProcessName
$handle = $proc.Handle
$action = if ($Disable) { 'Disabling' } else { 'Enabling' }
Write-Verbose ("{0} '{1}' for process {2}" -f $action, $Privilege, $name)
[Privilege]::EnablePrivilege($handle, $Privilege, [bool]$Disable)
}
catch {
throw
}
}
}
并调用两个函数:
Enable-Privilege -Privilege SeSecurityPrivilege
Repair-DirectoryPermissions -Path 'D:\Blah'