Question:
Issue: I wish to programmaticly (with PowerShell) take ownership of a file that I have absolutely no permissions on.
Update: I’ve thoroughly rewritten the question to give steps to reproduce the issue. Here’s what I’m doing:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
########################################################## # Logon as UserA ########################################################## $file = "C:\temp\file.txt" new-item C:\temp -type dir new-item $file -type file # Remove inheritence $isProtected = $true $preserveInheritance = $true $FileSecurity = Get-ACL $file $FileSecurity.SetAccessRuleProtection($isProtected, $preserveInheritance) Set-ACL $file -AclObject $FileSecurity # Remove authenticated users $user = "Authenticated Users" $permission = "Modify" $Account = New-Object System.Security.Principal.NTAccount($user) $FileSystemRights = [System.Security.AccessControl.FileSystemRights]$permission $InheritanceFlag = [System.Security.AccessControl.InheritanceFlags]"ContainerInherit, ObjectInherit" $PropagationFlag = [System.Security.AccessControl.PropagationFlags]"None" $AccessControlType =[System.Security.AccessControl.AccessControlType]::Allow $FileSystemAccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($Account, $FileSystemRights, $InheritanceFlag, $PropagationFlag, $AccessControlType) $FileSecurity = Get-ACL $file $FileSecurity.RemoveAccessRuleAll($FileSystemAccessRule) Set-ACL $file -AclObject $FileSecurity # Remove local users $user = "BUILTIN\Users" $permission = "ReadAndExecute" $Account = New-Object System.Security.Principal.NTAccount($user) $FileSystemRights = [System.Security.AccessControl.FileSystemRights]$permission $InheritanceFlag = [System.Security.AccessControl.InheritanceFlags]"ContainerInherit, ObjectInherit" $PropagationFlag = [System.Security.AccessControl.PropagationFlags]"None" $AccessControlType =[System.Security.AccessControl.AccessControlType]::Allow $FileSystemAccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($Account, $FileSystemRights, $InheritanceFlag, $PropagationFlag, $AccessControlType) $FileSecurity = Get-ACL $file $FileSecurity.RemoveAccessRuleAll($FileSystemAccessRule) Set-ACL $file -AclObject $FileSecurity # Give the current user Full Control $user = $env:username $permission = "FullControl" $FileSystemRights = [System.Security.AccessControl.FileSystemRights]$permission $AccessControlType =[System.Security.AccessControl.AccessControlType]::Allow $Account = New-Object System.Security.Principal.NTAccount($user) $FileSystemAccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($Account, $FileSystemRights, $AccessControlType) $FileSecurity = Get-ACL $file $FileSecurity.AddAccessRule($FileSystemAccessRule) Set-ACL $file -AclObject $FileSecurity # Remove local administrators $user = "BUILTIN\Administrators" $permission = "FullControl" $Account = New-Object System.Security.Principal.NTAccount($user) $FileSystemRights = [System.Security.AccessControl.FileSystemRights]$permission $InheritanceFlag = [System.Security.AccessControl.InheritanceFlags]"ContainerInherit, ObjectInherit" $PropagationFlag = [System.Security.AccessControl.PropagationFlags]"None" $AccessControlType =[System.Security.AccessControl.AccessControlType]::Allow $FileSystemAccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($Account, $FileSystemRights, $InheritanceFlag, $PropagationFlag, $AccessControlType) $FileSecurity = Get-ACL $file $FileSecurity.RemoveAccessRuleAll($FileSystemAccessRule) Set-ACL $file -AclObject $FileSecurity # Set the owner to be the current user $user = $env:username $Account = New-Object System.Security.Principal.NTAccount($user) $FileSecurity = new-object System.Security.AccessControl.FileSecurity $FileSecurity.SetOwner($Account) [System.IO.File]::SetAccessControl($file, $FileSecurity) ########################################################## # Log off the server as UserA and logon as UserB ########################################################## $file = "C:\temp\file.txt" # Take ownership $user = $env:username $Account = New-Object System.Security.Principal.NTAccount($user) $FileSecurity = new-object System.Security.AccessControl.FileSecurity $FileSecurity.SetOwner($Account) [System.IO.File]::SetAccessControl($file, $FileSecurity) |
This is throwing the error:
1 2 3 4 5 6 |
Exception calling "SetAccessControl" with "2" argument(s): "Attempted to perform an unauthorized operation." At line:1 char:35 + [System.IO.File]::SetAccessControl <<<< ($path, $FileSecurity) + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : DotNetMethodException |
Additional notes:
- $error[0].innerexception is null.
- The steps taken as UserA ensured that userB has absolutely no permissions on
C:\temp\file.txt
. - running
[System.IO.File]::GetAccessControl($path)
throws a similar
error (which is expected) - I am of course right-clicking PowerShell and choosing “Run as Administrator”.
- I’ve tried disabling UAC, but that does not make a difference.
- I can take ownership through the GUI so there should be a way to do this programmatically with PowerShell.
What am I doing wrong?
Update and answer:
The accepted answer I posted, works, but seems to be overkill. Simply referencing the file via a UNC path seems to do the trick:
1 2 3 4 5 6 7 8 9 |
$file = "\\localhost\\c$\temp\file.txt" # Take ownership $user = $env:username $Account = New-Object System.Security.Principal.NTAccount($user) $FileSecurity = new-object System.Security.AccessControl.FileSecurity $FileSecurity.SetOwner($Account) [System.IO.File]::SetAccessControl($file, $FileSecurity) |
Answer:
I’ve figured this out. I can only be done with SE_RESTORE_NAME permissions.
I learned how to do that from:
http://cosmoskey.blogspot.com/2010/07/setting-owner-on-acl-in-powershell.html
And with a comment from: http://fixingitpro.com/2011/07/08/set-owner-with-powershell-%E2%80%9Cthe-security-identifier-is-not-allowed-to-be-the-owner-of-this-object%E2%80%9D/
Here’s the full command that works for me:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
$code = @" using System; using System.Runtime.InteropServices; namespace CosmosKey.Utils { 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 const string SE_ASSIGNPRIMARYTOKEN_NAME = "SeAssignPrimaryTokenPrivilege"; public const string SE_AUDIT_NAME = "SeAuditPrivilege"; public const string SE_BACKUP_NAME = "SeBackupPrivilege"; public const string SE_CHANGE_NOTIFY_NAME = "SeChangeNotifyPrivilege"; public const string SE_CREATE_GLOBAL_NAME = "SeCreateGlobalPrivilege"; public const string SE_CREATE_PAGEFILE_NAME = "SeCreatePagefilePrivilege"; public const string SE_CREATE_PERMANENT_NAME = "SeCreatePermanentPrivilege"; public const string SE_CREATE_SYMBOLIC_LINK_NAME = "SeCreateSymbolicLinkPrivilege"; public const string SE_CREATE_TOKEN_NAME = "SeCreateTokenPrivilege"; public const string SE_DEBUG_NAME = "SeDebugPrivilege"; public const string SE_ENABLE_DELEGATION_NAME = "SeEnableDelegationPrivilege"; public const string SE_IMPERSONATE_NAME = "SeImpersonatePrivilege"; public const string SE_INC_BASE_PRIORITY_NAME = "SeIncreaseBasePriorityPrivilege"; public const string SE_INCREASE_QUOTA_NAME = "SeIncreaseQuotaPrivilege"; public const string SE_INC_WORKING_SET_NAME = "SeIncreaseWorkingSetPrivilege"; public const string SE_LOAD_DRIVER_NAME = "SeLoadDriverPrivilege"; public const string SE_LOCK_MEMORY_NAME = "SeLockMemoryPrivilege"; public const string SE_MACHINE_ACCOUNT_NAME = "SeMachineAccountPrivilege"; public const string SE_MANAGE_VOLUME_NAME = "SeManageVolumePrivilege"; public const string SE_PROF_SINGLE_PROCESS_NAME = "SeProfileSingleProcessPrivilege"; public const string SE_RELABEL_NAME = "SeRelabelPrivilege"; public const string SE_REMOTE_SHUTDOWN_NAME = "SeRemoteShutdownPrivilege"; public const string SE_RESTORE_NAME = "SeRestorePrivilege"; public const string SE_SECURITY_NAME = "SeSecurityPrivilege"; public const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege"; public const string SE_SYNC_AGENT_NAME = "SeSyncAgentPrivilege"; public const string SE_SYSTEM_ENVIRONMENT_NAME = "SeSystemEnvironmentPrivilege"; public const string SE_SYSTEM_PROFILE_NAME = "SeSystemProfilePrivilege"; public const string SE_SYSTEMTIME_NAME = "SeSystemtimePrivilege"; public const string SE_TAKE_OWNERSHIP_NAME = "SeTakeOwnershipPrivilege"; public const string SE_TCB_NAME = "SeTcbPrivilege"; public const string SE_TIME_ZONE_NAME = "SeTimeZonePrivilege"; public const string SE_TRUSTED_CREDMAN_ACCESS_NAME = "SeTrustedCredManAccessPrivilege"; public const string SE_UNDOCK_NAME = "SeUndockPrivilege"; public const string SE_UNSOLICITED_INPUT_NAME = "SeUnsolicitedInputPrivilege"; 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; } } } } "@ # Take ownership add-type $code [void][CosmosKey.Utils.TokenManipulator]::AddPrivilege([CosmosKey.Utils.TokenManipulator]::SE_RESTORE_NAME) $file = "\\$env:computername\c$\temp\file.txt" $user = $env:username $Account = New-Object System.Security.Principal.NTAccount($user) $FileSecurity = new-object System.Security.AccessControl.FileSecurity $FileSecurity.SetOwner($Account) [System.IO.File]::SetAccessControl($file, $FileSecurity) [void][CosmosKey.Utils.TokenManipulator]::RemovePrivilege([CosmosKey.Utils.TokenManipulator]::SE_RESTORE_NAME) |