无法从 ACL 中删除 ACE
Unable to remove ACE from ACL
我们想要完全清除文件夹的 NTFS ACL
,并且只用 ACE
Builtin\Administrator : Full Control
填充 ACL
。下面的代码适用于大多数文件夹,但在一个特定文件夹上失败:
$Path = 'E:\DEPARTMENTS\Gemensam'
$BuiltinAdmin = [System.Security.Principal.NTAccount]'Builtin\Administrators'
$AdminFullControlAce = New-Object System.Security.AccessControl.FileSystemAccessRule(
$BuiltinAdmin,
[System.Security.AccessControl.FileSystemRights]::FullControl,
[System.Security.AccessControl.InheritanceFlags]'ContainerInherit,ObjectInherit',
[System.Security.AccessControl.PropagationFlags]::None,
[System.Security.AccessControl.AccessControlType]::Allow
)
(Get-Acl $Path).Access
$FolderItem = Get-Item -Path $Path -EA Stop
$Acl = $FolderItem.GetAccessControl()
Write-Verbose 'Set owner'
$Acl.SetOwner($BuiltinAdmin)
$FolderItem.SetAccessControl($Acl)
Write-Verbose 'Disable inheritance'
$Acl = $FolderItem.GetAccessControl()
$Acl.SetAccessRuleProtection($True, $False)
$FolderItem.SetAccessControl($Acl)
Write-Verbose 'Remove all ACEs from the ACL'
$Acl = $FolderItem.GetAccessControl()
$Acl.Access.ForEach({$Acl.RemoveAccessRule($_)})
Write-Verbose 'Add Admin and set the new ACL'
$acl.AddAccessRule($AdminFullControlAce)
$FolderItem.SetAccessControl($Acl)
Write-Verbose 'ACL corrected'
(Get-Acl $Path).Access
这段代码的输出是:
FileSystemRights : FullControl
AccessControlType : Allow
IdentityReference : BUILTIN\Administrators
IsInherited : False
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : None
FileSystemRights : Modify, Synchronize
AccessControlType : Allow
IdentityReference : GROUPHC\SWE CEM KVB EV
IsInherited : False
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : None
VERBOSE: Set owner
VERBOSE: Disable inheritance
VERBOSE: Remove all ACEs from the ACL
True
True
VERBOSE: Add Admin and set the new ACL
VERBOSE: ACL corrected
FileSystemRights : FullControl
AccessControlType : Allow
IdentityReference : BUILTIN\Administrators
IsInherited : False
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : None
FileSystemRights : Modify, Synchronize
AccessControlType : Allow
IdentityReference : GROUPHC\SWE CEM KVB EV
IsInherited : False
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : None
出于某种原因,似乎无法删除 GROUPHC\SWE CEM KVB EV
的 ACE
。即使 Get-ACL
和 Set-ACL
it doesn't work. We've also tried to push the ACL
after every change as indicated here, but that doesn't work either. According to the docs 继承被正确删除,所以它不能是继承的 ACE
.
如有任何帮助,我们将不胜感激。
为避免所有权问题,我们首先 运行 以下代码:
#region Get super powers
$AdjustTokenPrivileges = @"
using System;
using System.Runtime.InteropServices;
public class TokenManipulator
{
[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("kernel32.dll", ExactSpelling = true)]
internal static extern IntPtr GetCurrentProcess();
[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_DISABLED = 0x00000000;
internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
internal const int TOKEN_QUERY = 0x00000008;
internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
public static bool AddPrivilege(string privilege)
{
try
{
bool retVal;
TokPriv1Luid tp;
IntPtr hproc = GetCurrentProcess();
IntPtr htok = IntPtr.Zero;
retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
tp.Count = 1;
tp.Luid = 0;
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;
}
catch (Exception ex)
{
throw ex;
}
}
public static bool RemovePrivilege(string privilege)
{
try
{
bool retVal;
TokPriv1Luid tp;
IntPtr hproc = GetCurrentProcess();
IntPtr htok = IntPtr.Zero;
retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
tp.Count = 1;
tp.Luid = 0;
tp.Attr = SE_PRIVILEGE_DISABLED;
retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid);
retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
return retVal;
}
catch (Exception ex)
{
throw ex;
}
}
}
"@
Try {
Write-Verbose 'Get super powers'
Add-Type $AdjustTokenPrivileges
[void][TokenManipulator]::AddPrivilege('SeRestorePrivilege')
[void][TokenManipulator]::AddPrivilege('SeBackupPrivilege')
[void][TokenManipulator]::AddPrivilege('SeTakeOwnershipPrivilege')
}
Catch {
throw "Failed getting super powers: $_"
}
#endregion
看我上面的评论:
Import-Module PSCX
Set-Privilege (new-object Pscx.Interop.TokenPrivilege "SeRestorePrivilege", $true) # Necessary to set Owner Permissions
Set-Privilege (new-object Pscx.Interop.TokenPrivilege "SeBackupPrivilege", $true) # Necessary to bypass Traverse Checking
Set-Privilege (new-object Pscx.Interop.TokenPrivilege "SeTakeOwnershipPrivilege", $true) # Necessary to override FilePermissions & take Ownership
现在在目标上递归使用 Get/Set ACL 命令
感谢 Theo 的评论,我们找到了解决该问题的方法。我们只需要创建一个空的 ACL
然后将我们的属性添加到对象中,之后就可以简单地应用它了:
$Path = 'E:\DEPARTMENTS\Gemensam'
$BuiltinAdmin = [System.Security.Principal.NTAccount]'Builtin\Administrators'
$AdminFullControlAce = New-Object System.Security.AccessControl.FileSystemAccessRule(
$BuiltinAdmin,
[System.Security.AccessControl.FileSystemRights]::FullControl,
[System.Security.AccessControl.InheritanceFlags]'ContainerInherit,ObjectInherit',
[System.Security.AccessControl.PropagationFlags]::None,
[System.Security.AccessControl.AccessControlType]::Allow
)
#region Create new ACL
$NewAcl = New-Object System.Security.AccessControl.DirectorySecurity
$NewAcl.SetOwner($BuiltinAdmin)
$NewAcl.SetAccessRuleProtection($true,$false)
$NewAcl.AddAccessRule($AdminFullControlAce)
#endregion
$FolderItem = Get-Item -Path $Path -EA Stop
$FolderItem.SetAccessControl($NewAcl)
$FolderAcl = $FolderItem.GetAccessControl()
$FolderAcl.Access | select IdentityReference, FileSystemRights
或者两次应用ACL:
$M = Get-Item -Path 'C:\YourFolder'
$Acl = $M.GetAccessControl()
$BuiltinAdmin = [System.Security.Principal.NTAccount]'Builtin\Administrators'
$InheritedDirAcl = New-Object System.Security.AccessControl.DirectorySecurity
$InheritedDirAcl.SetOwner($BuiltinAdmin)
$InheritedDirAcl.SetAccessRuleProtection($false,$false)
# This is a workaround for non inherited permissions
# that do not get removed when simply applying the new ACL
$Acl.Access | ForEach-Object {
$Acl.RemoveAccessRuleSpecific($_)
}
$M.SetAccessControl($Acl)
$M.SetAccessControl($InheritedDirAcl)
我们想要完全清除文件夹的 NTFS ACL
,并且只用 ACE
Builtin\Administrator : Full Control
填充 ACL
。下面的代码适用于大多数文件夹,但在一个特定文件夹上失败:
$Path = 'E:\DEPARTMENTS\Gemensam'
$BuiltinAdmin = [System.Security.Principal.NTAccount]'Builtin\Administrators'
$AdminFullControlAce = New-Object System.Security.AccessControl.FileSystemAccessRule(
$BuiltinAdmin,
[System.Security.AccessControl.FileSystemRights]::FullControl,
[System.Security.AccessControl.InheritanceFlags]'ContainerInherit,ObjectInherit',
[System.Security.AccessControl.PropagationFlags]::None,
[System.Security.AccessControl.AccessControlType]::Allow
)
(Get-Acl $Path).Access
$FolderItem = Get-Item -Path $Path -EA Stop
$Acl = $FolderItem.GetAccessControl()
Write-Verbose 'Set owner'
$Acl.SetOwner($BuiltinAdmin)
$FolderItem.SetAccessControl($Acl)
Write-Verbose 'Disable inheritance'
$Acl = $FolderItem.GetAccessControl()
$Acl.SetAccessRuleProtection($True, $False)
$FolderItem.SetAccessControl($Acl)
Write-Verbose 'Remove all ACEs from the ACL'
$Acl = $FolderItem.GetAccessControl()
$Acl.Access.ForEach({$Acl.RemoveAccessRule($_)})
Write-Verbose 'Add Admin and set the new ACL'
$acl.AddAccessRule($AdminFullControlAce)
$FolderItem.SetAccessControl($Acl)
Write-Verbose 'ACL corrected'
(Get-Acl $Path).Access
这段代码的输出是:
FileSystemRights : FullControl
AccessControlType : Allow
IdentityReference : BUILTIN\Administrators
IsInherited : False
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : None
FileSystemRights : Modify, Synchronize
AccessControlType : Allow
IdentityReference : GROUPHC\SWE CEM KVB EV
IsInherited : False
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : None
VERBOSE: Set owner
VERBOSE: Disable inheritance
VERBOSE: Remove all ACEs from the ACL
True
True
VERBOSE: Add Admin and set the new ACL
VERBOSE: ACL corrected
FileSystemRights : FullControl
AccessControlType : Allow
IdentityReference : BUILTIN\Administrators
IsInherited : False
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : None
FileSystemRights : Modify, Synchronize
AccessControlType : Allow
IdentityReference : GROUPHC\SWE CEM KVB EV
IsInherited : False
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : None
出于某种原因,似乎无法删除 GROUPHC\SWE CEM KVB EV
的 ACE
。即使 Get-ACL
和 Set-ACL
it doesn't work. We've also tried to push the ACL
after every change as indicated here, but that doesn't work either. According to the docs 继承被正确删除,所以它不能是继承的 ACE
.
如有任何帮助,我们将不胜感激。
为避免所有权问题,我们首先 运行 以下代码:
#region Get super powers
$AdjustTokenPrivileges = @"
using System;
using System.Runtime.InteropServices;
public class TokenManipulator
{
[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("kernel32.dll", ExactSpelling = true)]
internal static extern IntPtr GetCurrentProcess();
[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_DISABLED = 0x00000000;
internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
internal const int TOKEN_QUERY = 0x00000008;
internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
public static bool AddPrivilege(string privilege)
{
try
{
bool retVal;
TokPriv1Luid tp;
IntPtr hproc = GetCurrentProcess();
IntPtr htok = IntPtr.Zero;
retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
tp.Count = 1;
tp.Luid = 0;
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;
}
catch (Exception ex)
{
throw ex;
}
}
public static bool RemovePrivilege(string privilege)
{
try
{
bool retVal;
TokPriv1Luid tp;
IntPtr hproc = GetCurrentProcess();
IntPtr htok = IntPtr.Zero;
retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
tp.Count = 1;
tp.Luid = 0;
tp.Attr = SE_PRIVILEGE_DISABLED;
retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid);
retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
return retVal;
}
catch (Exception ex)
{
throw ex;
}
}
}
"@
Try {
Write-Verbose 'Get super powers'
Add-Type $AdjustTokenPrivileges
[void][TokenManipulator]::AddPrivilege('SeRestorePrivilege')
[void][TokenManipulator]::AddPrivilege('SeBackupPrivilege')
[void][TokenManipulator]::AddPrivilege('SeTakeOwnershipPrivilege')
}
Catch {
throw "Failed getting super powers: $_"
}
#endregion
看我上面的评论:
Import-Module PSCX
Set-Privilege (new-object Pscx.Interop.TokenPrivilege "SeRestorePrivilege", $true) # Necessary to set Owner Permissions
Set-Privilege (new-object Pscx.Interop.TokenPrivilege "SeBackupPrivilege", $true) # Necessary to bypass Traverse Checking
Set-Privilege (new-object Pscx.Interop.TokenPrivilege "SeTakeOwnershipPrivilege", $true) # Necessary to override FilePermissions & take Ownership
现在在目标上递归使用 Get/Set ACL 命令
感谢 Theo 的评论,我们找到了解决该问题的方法。我们只需要创建一个空的 ACL
然后将我们的属性添加到对象中,之后就可以简单地应用它了:
$Path = 'E:\DEPARTMENTS\Gemensam'
$BuiltinAdmin = [System.Security.Principal.NTAccount]'Builtin\Administrators'
$AdminFullControlAce = New-Object System.Security.AccessControl.FileSystemAccessRule(
$BuiltinAdmin,
[System.Security.AccessControl.FileSystemRights]::FullControl,
[System.Security.AccessControl.InheritanceFlags]'ContainerInherit,ObjectInherit',
[System.Security.AccessControl.PropagationFlags]::None,
[System.Security.AccessControl.AccessControlType]::Allow
)
#region Create new ACL
$NewAcl = New-Object System.Security.AccessControl.DirectorySecurity
$NewAcl.SetOwner($BuiltinAdmin)
$NewAcl.SetAccessRuleProtection($true,$false)
$NewAcl.AddAccessRule($AdminFullControlAce)
#endregion
$FolderItem = Get-Item -Path $Path -EA Stop
$FolderItem.SetAccessControl($NewAcl)
$FolderAcl = $FolderItem.GetAccessControl()
$FolderAcl.Access | select IdentityReference, FileSystemRights
或者两次应用ACL:
$M = Get-Item -Path 'C:\YourFolder'
$Acl = $M.GetAccessControl()
$BuiltinAdmin = [System.Security.Principal.NTAccount]'Builtin\Administrators'
$InheritedDirAcl = New-Object System.Security.AccessControl.DirectorySecurity
$InheritedDirAcl.SetOwner($BuiltinAdmin)
$InheritedDirAcl.SetAccessRuleProtection($false,$false)
# This is a workaround for non inherited permissions
# that do not get removed when simply applying the new ACL
$Acl.Access | ForEach-Object {
$Acl.RemoveAccessRuleSpecific($_)
}
$M.SetAccessControl($Acl)
$M.SetAccessControl($InheritedDirAcl)