问题
I'm trying to take ownership of a directory with the following code:
sd = win32security.SECURITY_DESCRIPTOR()
sd.SetSecurityDescriptorOwner(curUser, False)
win32security.SetFileSecurity("C:/ProgramData/Test",
win32security.OWNER_SECURITY_INFORMATION, sd)
The SetFileSecurity
call fails with an "Access denied" error.
The access rights for the current user have been removed from this directory. In Explorer I can see it, but when I try to open it, I first have to take ownership as an administrator. That works in Explorer, but the above code is executed with elevated permissions, and for some reason it still fails. Any suggestions?
回答1:
You can forcefully take ownership by enabling SeTakeOwnerShipPrivilege
, but of course only if your access token has this privilege (e.g. an elevated administrator). Also, you can forcefully assign ownership to another security principal, such as SYSTEM
, by enabling SeRestorePrivilege
. Without the latter, the assignment may fail with the error code ERROR_INVALID_OWNER
.
The following set_file_owner
function has a force
option that attempts to temporarily enable both of these privileges.
import win32api
import win32security
def set_file_owner(path, sid=None, force=False):
try:
hToken = win32security.OpenThreadToken(win32api.GetCurrentThread(),
win32security.TOKEN_ALL_ACCESS, True)
except win32security.error:
hToken = win32security.OpenProcessToken(win32api.GetCurrentProcess(),
win32security.TOKEN_ALL_ACCESS)
if sid is None:
sid = win32security.GetTokenInformation(hToken,
win32security.TokenOwner)
prev_state = ()
if force:
new_state = [(win32security.LookupPrivilegeValue(None, name),
win32security.SE_PRIVILEGE_ENABLED)
for name in (win32security.SE_TAKE_OWNERSHIP_NAME,
win32security.SE_RESTORE_NAME)]
prev_state = win32security.AdjustTokenPrivileges(hToken, False,
new_state)
try:
sd = win32security.SECURITY_DESCRIPTOR()
sd.SetSecurityDescriptorOwner(sid, False)
win32security.SetFileSecurity(path,
win32security.OWNER_SECURITY_INFORMATION, sd)
finally:
if prev_state:
win32security.AdjustTokenPrivileges(hToken, False, prev_state)
def get_file_owner(path):
sd = win32security.GetFileSecurity(path,
win32security.OWNER_SECURITY_INFORMATION)
sid = sd.GetSecurityDescriptorOwner()
return win32security.LookupAccountSid(None, sid)
Example
if __name__ == '__main__':
import os
import tempfile
import subprocess
username = os.environ['UserName']
test_path = tempfile.mkdtemp()
print('Test path: {}'.format(test_path))
subprocess.call(['icacls.exe', test_path, '/setowner', 'SYSTEM'],
creationflags=8)
owner = get_file_owner(test_path)
print('Initial owner: {}\\{}'.format(owner[1], owner[0]))
try:
print('Denying write owner access')
subprocess.call(['icacls.exe', test_path, '/deny',
'{}:(WO)'.format(username)], creationflags=8)
try:
set_file_owner(test_path)
except win32security.error:
print('Trying with force=True')
try:
set_file_owner(test_path, force=True)
except win32security.error:
pass
finally:
owner = get_file_owner(test_path)
print('Final owner: {}\\{}'.format(owner[1], owner[0]))
os.rmdir(test_path)
Output
Test path: C:\Users\eryksun\AppData\Local\Temp\tmpizgemrdz
Initial owner: NT AUTHORITY\SYSTEM
Denying write owner access
Trying with force=True
Final owner: BUILTIN\Administrators
回答2:
I've based on Eryk's work to make a full recursive ACL and onwership handling routing for NTFS files under Windows here: https://stackoverflow.com/a/61041460/2635443
来源:https://stackoverflow.com/questions/41081263/taking-directory-ownership-on-windows-with-python-results-in-access-denied-err