Python - 获取 windows 文件夹 ACL 权限
Python - Get windows folder ACL permissions
我正在寻找使用 Python 27 获取文件夹 ACL 权限的示例。
我需要这样的结果:domain\username - FullControl, domain\username Modify
谢谢!
这是使用 Tim Golden wmi module. It selects an instance of Win32_LogicalFileSecuritySetting
for a given path. It calls the GetSecurityDescriptor
method to get a Win32_SecurityDescriptor
的 WMI 示例。我用它来创建 Ace
和 FileSecurity
namedtuple 实例。我添加了一些方法来测试 ACE 授予、拒绝或审核的访问权限,并以类似于 icacls 使用的格式输出数据。
我还包括 ctypes 代码以启用 SeSecurityPrivilege
,这是读取系统访问控制列表 (SACL) 所必需的。
导入和常量
import os
import wmi
import collections
import ctypes
from ctypes import wintypes
SE_OWNER_DEFAULTED = 0x0001
SE_GROUP_DEFAULTED = 0x0002
SE_DACL_PRESENT = 0x0004
SE_DACL_DEFAULTED = 0x0008
SE_SACL_PRESENT = 0x0010
SE_SACL_DEFAULTED = 0x0020
SE_DACL_AUTO_INHERIT_REQ = 0x0100
SE_SACL_AUTO_INHERIT_REQ = 0x0200
SE_DACL_AUTO_INHERITED = 0x0400
SE_SACL_AUTO_INHERITED = 0x0800
SE_DACL_PROTECTED = 0x1000
SE_SACL_PROTECTED = 0x2000
SE_SELF_RELATIVE = 0x8000
OBJECT_INHERIT_ACE = 0x01
CONTAINER_INHERIT_ACE = 0x02
NO_PROPAGATE_INHERIT_ACE = 0x04
INHERIT_ONLY_ACE = 0x08
INHERITED_ACE = 0x10
SUCCESSFUL_ACCESS_ACE_FLAG = 0x40
FAILED_ACCESS_ACE_FLAG = 0x80
ACCESS_ALLOWED_ACE_TYPE = 0
ACCESS_DENIED_ACE_TYPE = 1
SYSTEM_AUDIT_ACE_TYPE = 2
DELETE = 0x00010000 # DE
READ_CONTROL = 0x00020000 # RC
WRITE_DAC = 0x00040000 # WDAC
WRITE_OWNER = 0x00080000 # WO
SYNCHRONIZE = 0x00100000 # S
ACCESS_SYSTEM_SECURITY = 0x01000000 # AS
GENERIC_READ = 0x80000000 # GR
GENERIC_WRITE = 0x40000000 # GW
GENERIC_EXECUTE = 0x20000000 # GE
GENERIC_ALL = 0x10000000 # GA
FILE_READ_DATA = 0x00000001 # RD
FILE_LIST_DIRECTORY = 0x00000001
FILE_WRITE_DATA = 0x00000002 # WD
FILE_ADD_FILE = 0x00000002
FILE_APPEND_DATA = 0x00000004 # AD
FILE_ADD_SUBDIRECTORY = 0x00000004
FILE_READ_EA = 0x00000008 # REA
FILE_WRITE_EA = 0x00000010 # WEA
FILE_EXECUTE = 0x00000020 # X
FILE_TRAVERSE = 0x00000020
FILE_DELETE_CHILD = 0x00000040 # DC
FILE_READ_ATTRIBUTES = 0x00000080 # RA
FILE_WRITE_ATTRIBUTES = 0x00000100 # WA
FILE_GENERIC_READ = (FILE_READ_DATA |
FILE_READ_EA |
FILE_READ_ATTRIBUTES |
READ_CONTROL |
SYNCHRONIZE)
FILE_GENERIC_WRITE = (FILE_WRITE_DATA |
FILE_APPEND_DATA |
FILE_WRITE_EA |
FILE_WRITE_ATTRIBUTES |
READ_CONTROL |
SYNCHRONIZE)
FILE_GENERIC_EXECUTE = (FILE_EXECUTE |
FILE_READ_ATTRIBUTES |
READ_CONTROL |
SYNCHRONIZE)
FILE_ALL_ACCESS = 0x001F01FF
FILE_MODIIFY_ACCESS = FILE_ALL_ACCESS & ~(FILE_DELETE_CHILD |
WRITE_DAC |
WRITE_OWNER)
FILE_READ_EXEC_ACCESS = FILE_GENERIC_READ | FILE_GENERIC_EXECUTE
FILE_DELETE_ACCESS = DELETE | SYNCHRONIZE
类
_Ace = collections.namedtuple('_Ace',
'ace_type flags mask mapped_mask sid trustee')
class Ace(_Ace):
def __new__(cls, ace_type, flags, mask, sid, trustee):
mapped_mask = cls._map_generic(mask)
return super(Ace, cls).__new__(cls, ace_type, flags,
mask, mapped_mask, sid, trustee)
@staticmethod
def _map_generic(mask):
if mask & GENERIC_READ:
mask = (mask & ~GENERIC_READ) | FILE_GENERIC_READ
if mask & GENERIC_WRITE:
mask = (mask & ~GENERIC_WRITE) | FILE_GENERIC_WRITE
if mask & GENERIC_EXECUTE:
mask = (mask & ~GENERIC_EXECUTE) | FILE_GENERIC_EXECUTE
if mask & GENERIC_ALL:
mask = (mask & ~GENERIC_ALL) | FILE_ALL_ACCESS
return mask
def inherited(self): # I
return bool(self.flags & INHERITED_ACE)
def object_inherit(self): # OI
return bool(self.flags & OBJECT_INHERIT_ACE)
def container_inherit(self): # CI
return bool(self.flags & CONTAINER_INHERIT_ACE)
def inherit_only(self): # IO
return bool(self.flags & INHERIT_ONLY_ACE)
def no_propagate(self): # NP
return bool(self.flags & NO_PROPAGATE_INHERIT_ACE)
def no_access(self): # N
return self.mapped_mask == 0
def full_access(self): # F
return self.mapped_mask == FILE_ALL_ACCESS
def modify_access(self): # M
return self.mapped_mask == FILE_MODIIFY_ACCESS
def read_exec_access(self): # RX
return self.mapped_mask == FILE_READ_EXEC_ACCESS
def read_only_access(self): # R
return self.mapped_mask == FILE_GENERIC_READ
def write_only_access(self): # W
return self.mapped_mask == FILE_GENERIC_WRITE
def delete_access(self): # D
return self.mapped_mask == FILE_DELETE_ACCESS
def get_file_rights(self):
if self.no_access(): return ['N']
if self.full_access(): return ['F']
if self.modify_access(): return ['M']
if self.read_exec_access(): return ['RX']
if self.read_only_access(): return ['R']
if self.write_only_access(): return ['W']
if self.delete_access(): return ['D']
rights = []
for right, name in ((DELETE, 'DE'), (READ_CONTROL, 'RC'),
(WRITE_DAC, 'WDAC'), (WRITE_OWNER, 'WO'),
(SYNCHRONIZE, 'S'),
(ACCESS_SYSTEM_SECURITY, 'AS'),
(GENERIC_READ, 'GR'), (GENERIC_WRITE, 'GW'),
(GENERIC_EXECUTE, 'GE'), (GENERIC_ALL, 'GA'),
(FILE_READ_DATA, 'RD'), (FILE_WRITE_DATA, 'WD'),
(FILE_APPEND_DATA, 'AD'), (FILE_READ_EA, 'REA'),
(FILE_WRITE_EA, 'WEA'), (FILE_EXECUTE, 'X'),
(FILE_DELETE_CHILD, 'DC'),
(FILE_READ_ATTRIBUTES, 'RA'),
(FILE_WRITE_ATTRIBUTES, 'WA')):
if self.mask & right:
rights.append(name)
return rights
def granted_access(self, mask):
return bool(self.mapped_mask & self._map_generic(mask))
def __str__(self):
trustee = self.trustee if self.trustee else self.sid
access = []
if self.ace_type == ACCESS_DENIED_ACE_TYPE:
access.append('(DENY)')
elif self.ace_type == SYSTEM_AUDIT_ACE_TYPE:
access.append('(AUDIT)')
if self.inherited(): access.append('(I)')
if self.object_inherit(): access.append('(OI)')
if self.container_inherit(): access.append('(CI)')
if self.inherit_only(): access.append('(IO)')
if self.no_propagate(): acccess.append('(NP)')
access.append('(%s)' % ','.join(self.get_file_rights()))
return '%s:%s' % (trustee, ''.join(access))
_FileSecurity = collections.namedtuple('_FileSecurity',
'path owner_permissions owner group '
'owner_sid group_sid flags dacl sacl')
class FileSecurity(_FileSecurity):
def __str__(self):
owner = self.owner if self.owner else self.owner_sid
group = self.group if self.group else self.group_sid
items = ['Path: %s' % self.path,
'Owner: %s' % owner,
'Group: %s' % group]
if self.dacl:
items += ['DACL: %s' %
'\n '.join(str(x) for x in self.dacl)]
if self.sacl:
items += ['SACL: %s' %
'\n '.join(str(x) for x in self.sacl)]
return '\n'.join(items)
函数
def list_acl(wmi_acl):
acl = []
for entry in wmi_acl:
trustee = entry.Trustee.Name
if trustee and entry.Trustee.Domain:
trustee = '%s\%s' % (entry.Trustee.Domain, trustee)
mask = entry.AccessMask
if mask < 0:
mask += 2 ** 32
ace = Ace(entry.AceType, entry.AceFlags, mask,
entry.Trustee.SIDString, trustee)
acl.append(ace)
return acl
# Win32_LogicalFileSecuritySetting
# https://msdn.microsoft.com/en-us/library/aa394180
WQL_LFSS = 'SELECT * FROM Win32_LogicalFileSecuritySetting WHERE Path="%s"'
wmi_ns = wmi.WMI()
def get_file_security(path):
path = os.path.abspath(path)
os.stat(path) # ensure path exists
lfss = wmi_ns.query(WQL_LFSS % (path,))[0]
sd = lfss.GetSecurityDescriptor()[0]
owner = sd.Owner.Name
if owner and sd.Owner.Domain:
owner = '%s\%s' % (sd.Owner.Domain, owner)
group = sd.Group.Name
if group and sd.Group.Domain:
group = '%s\%s' % (sd.Group.Domain, group)
dacl = sacl = ()
if sd.ControlFlags & SE_DACL_PRESENT:
dacl = tuple(list_acl(sd.DACL))
if sd.ControlFlags & SE_SACL_PRESENT:
sacl = tuple(list_acl(sd.SACL))
return FileSecurity(lfss.Path,
lfss.OwnerPermissions,
owner, group,
sd.Owner.SIDString,
sd.Group.SIDString,
sd.ControlFlags,
dacl, sacl)
访问 SACL 需要 SeSecurityPrivilege
。这是一些启用特权的 ctypes 代码:
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
advapi32 = ctypes.WinDLL('advapi32', use_last_error=True)
ERROR_NOT_ALL_ASSIGNED = 0x0514
SE_PRIVILEGE_ENABLED = 0x00000002
TOKEN_ALL_ACCESS = 0x000F0000 | 0x01FF
class LUID(ctypes.Structure):
_fields_ = (('LowPart', wintypes.DWORD),
('HighPart', wintypes.LONG))
class LUID_AND_ATTRIBUTES(ctypes.Structure):
_fields_ = (('Luid', LUID),
('Attributes', wintypes.DWORD))
class TOKEN_PRIVILEGES(ctypes.Structure):
_fields_ = (('PrivilegeCount', wintypes.DWORD),
('Privileges', LUID_AND_ATTRIBUTES * 1))
def __init__(self, PrivilegeCount=1, *args):
super(TOKEN_PRIVILEGES, self).__init__(PrivilegeCount, *args)
PDWORD = ctypes.POINTER(wintypes.DWORD)
PHANDLE = ctypes.POINTER(wintypes.HANDLE)
PLUID = ctypes.POINTER(LUID)
PTOKEN_PRIVILEGES = ctypes.POINTER(TOKEN_PRIVILEGES)
def errcheck_bool(result, func, args):
if not result:
raise ctypes.WinError(ctypes.get_last_error())
return args
kernel32.CloseHandle.argtypes = (wintypes.HANDLE,)
kernel32.GetCurrentProcess.errcheck = errcheck_bool
kernel32.GetCurrentProcess.restype = wintypes.HANDLE
# https://msdn.microsoft.com/en-us/library/aa379295
advapi32.OpenProcessToken.errcheck = errcheck_bool
advapi32.OpenProcessToken.argtypes = (
wintypes.HANDLE, # _In_ ProcessHandle
wintypes.DWORD, # _In_ DesiredAccess
PHANDLE) # _Out_ TokenHandle
# https://msdn.microsoft.com/en-us/library/aa379180
advapi32.LookupPrivilegeValueW.errcheck = errcheck_bool
advapi32.LookupPrivilegeValueW.argtypes = (
wintypes.LPCWSTR, # _In_opt_ lpSystemName
wintypes.LPCWSTR, # _In_ lpName
PLUID) # _Out_ lpLuid
# https://msdn.microsoft.com/en-us/library/aa375202
advapi32.AdjustTokenPrivileges.errcheck = errcheck_bool
advapi32.AdjustTokenPrivileges.argtypes = (
wintypes.HANDLE, # _In_ TokenHandle
wintypes.BOOL, # _In_ DisableAllPrivileges
PTOKEN_PRIVILEGES, # _In_opt_ NewState
wintypes.DWORD, # _In_ BufferLength
PTOKEN_PRIVILEGES, # _Out_opt_ PreviousState
PDWORD) # _Out_opt_ ReturnLength
def enable_privilege(privilege):
hToken = wintypes.HANDLE()
luid = LUID()
tp = TOKEN_PRIVILEGES()
advapi32.LookupPrivilegeValueW(None, privilege, ctypes.byref(luid))
tp.Privileges[0].Luid = luid
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED
advapi32.OpenProcessToken(kernel32.GetCurrentProcess(),
TOKEN_ALL_ACCESS,
ctypes.byref(hToken))
try:
advapi32.AdjustTokenPrivileges(hToken, False,
ctypes.byref(tp),
ctypes.sizeof(tp),
None, None)
if ctypes.get_last_error() == ERROR_NOT_ALL_ASSIGNED:
raise ctypes.WinError(ERROR_NOT_ALL_ASSIGNED)
finally:
kernel32.CloseHandle(hToken)
def disable_privilege(privilege):
hToken = wintypes.HANDLE()
luid = LUID()
tp = TOKEN_PRIVILEGES()
advapi32.LookupPrivilegeValueW(None, privilege, ctypes.byref(luid))
tp.Privileges[0].Luid = luid
tp.Privileges[0].Attributes = 0
advapi32.OpenProcessToken(kernel32.GetCurrentProcess(),
TOKEN_ALL_ACCESS,
ctypes.byref(hToken))
try:
advapi32.AdjustTokenPrivileges(hToken, False,
ctypes.byref(tp),
ctypes.sizeof(tp),
None, None)
if ctypes.get_last_error() == ERROR_NOT_ALL_ASSIGNED:
raise ctypes.WinError(ERROR_NOT_ALL_ASSIGNED)
finally:
kernel32.CloseHandle(hToken)
例如,我向 "Program Files" 目录添加了审计 ACE,以记录任何人更改目录权限或所有者的任何尝试。此 ACE 类型存储在系统访问控制列表 (SACL) 中。
>>> enable_privilege('SeSecurityPrivilege')
>>> print get_file_security('C:\Program Files')
Path : C:\Program Files
Owner: NT SERVICE\TrustedInstaller
Group: NT SERVICE\TrustedInstaller
DACL : NT SERVICE\TrustedInstaller:(F)
NT SERVICE\TrustedInstaller:(CI)(IO)(F)
NT AUTHORITY\SYSTEM:(M)
NT AUTHORITY\SYSTEM:(OI)(CI)(IO)(F)
BUILTIN\Administrators:(M)
BUILTIN\Administrators:(OI)(CI)(IO)(F)
BUILTIN\Users:(RX)
BUILTIN\Users:(OI)(CI)(IO)(RX)
CREATOR OWNER:(OI)(CI)(IO)(F)
APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES:(RX)
APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES:(OI)(CI)(IO)(RX)
SACL : Everyone:(AUDIT)(WDAC,WO)
下面显示了拒绝 ACE 是如何出现的:
>>> f = open('tempfile', 'w'); f.close()
>>> os.system('icacls tempfile /deny Guests:(M)')
processed file: tempfile
Successfully processed 1 files; Failed processing 0 files
0
>>> print get_file_security('tempfile')
Path : C:\Temp\tempfile
Owner: BUILTIN\Administrators
Group: THISPC\None
DACL : BUILTIN\Guests:(DENY)(M)
BUILTIN\Administrators:(I)(F)
NT AUTHORITY\SYSTEM:(I)(F)
BUILTIN\Users:(I)(RX)
NT AUTHORITY\Authenticated Users:(I)(M)
我正在寻找使用 Python 27 获取文件夹 ACL 权限的示例。 我需要这样的结果:domain\username - FullControl, domain\username Modify
谢谢!
这是使用 Tim Golden wmi module. It selects an instance of Win32_LogicalFileSecuritySetting
for a given path. It calls the GetSecurityDescriptor
method to get a Win32_SecurityDescriptor
的 WMI 示例。我用它来创建 Ace
和 FileSecurity
namedtuple 实例。我添加了一些方法来测试 ACE 授予、拒绝或审核的访问权限,并以类似于 icacls 使用的格式输出数据。
我还包括 ctypes 代码以启用 SeSecurityPrivilege
,这是读取系统访问控制列表 (SACL) 所必需的。
导入和常量
import os
import wmi
import collections
import ctypes
from ctypes import wintypes
SE_OWNER_DEFAULTED = 0x0001
SE_GROUP_DEFAULTED = 0x0002
SE_DACL_PRESENT = 0x0004
SE_DACL_DEFAULTED = 0x0008
SE_SACL_PRESENT = 0x0010
SE_SACL_DEFAULTED = 0x0020
SE_DACL_AUTO_INHERIT_REQ = 0x0100
SE_SACL_AUTO_INHERIT_REQ = 0x0200
SE_DACL_AUTO_INHERITED = 0x0400
SE_SACL_AUTO_INHERITED = 0x0800
SE_DACL_PROTECTED = 0x1000
SE_SACL_PROTECTED = 0x2000
SE_SELF_RELATIVE = 0x8000
OBJECT_INHERIT_ACE = 0x01
CONTAINER_INHERIT_ACE = 0x02
NO_PROPAGATE_INHERIT_ACE = 0x04
INHERIT_ONLY_ACE = 0x08
INHERITED_ACE = 0x10
SUCCESSFUL_ACCESS_ACE_FLAG = 0x40
FAILED_ACCESS_ACE_FLAG = 0x80
ACCESS_ALLOWED_ACE_TYPE = 0
ACCESS_DENIED_ACE_TYPE = 1
SYSTEM_AUDIT_ACE_TYPE = 2
DELETE = 0x00010000 # DE
READ_CONTROL = 0x00020000 # RC
WRITE_DAC = 0x00040000 # WDAC
WRITE_OWNER = 0x00080000 # WO
SYNCHRONIZE = 0x00100000 # S
ACCESS_SYSTEM_SECURITY = 0x01000000 # AS
GENERIC_READ = 0x80000000 # GR
GENERIC_WRITE = 0x40000000 # GW
GENERIC_EXECUTE = 0x20000000 # GE
GENERIC_ALL = 0x10000000 # GA
FILE_READ_DATA = 0x00000001 # RD
FILE_LIST_DIRECTORY = 0x00000001
FILE_WRITE_DATA = 0x00000002 # WD
FILE_ADD_FILE = 0x00000002
FILE_APPEND_DATA = 0x00000004 # AD
FILE_ADD_SUBDIRECTORY = 0x00000004
FILE_READ_EA = 0x00000008 # REA
FILE_WRITE_EA = 0x00000010 # WEA
FILE_EXECUTE = 0x00000020 # X
FILE_TRAVERSE = 0x00000020
FILE_DELETE_CHILD = 0x00000040 # DC
FILE_READ_ATTRIBUTES = 0x00000080 # RA
FILE_WRITE_ATTRIBUTES = 0x00000100 # WA
FILE_GENERIC_READ = (FILE_READ_DATA |
FILE_READ_EA |
FILE_READ_ATTRIBUTES |
READ_CONTROL |
SYNCHRONIZE)
FILE_GENERIC_WRITE = (FILE_WRITE_DATA |
FILE_APPEND_DATA |
FILE_WRITE_EA |
FILE_WRITE_ATTRIBUTES |
READ_CONTROL |
SYNCHRONIZE)
FILE_GENERIC_EXECUTE = (FILE_EXECUTE |
FILE_READ_ATTRIBUTES |
READ_CONTROL |
SYNCHRONIZE)
FILE_ALL_ACCESS = 0x001F01FF
FILE_MODIIFY_ACCESS = FILE_ALL_ACCESS & ~(FILE_DELETE_CHILD |
WRITE_DAC |
WRITE_OWNER)
FILE_READ_EXEC_ACCESS = FILE_GENERIC_READ | FILE_GENERIC_EXECUTE
FILE_DELETE_ACCESS = DELETE | SYNCHRONIZE
类
_Ace = collections.namedtuple('_Ace',
'ace_type flags mask mapped_mask sid trustee')
class Ace(_Ace):
def __new__(cls, ace_type, flags, mask, sid, trustee):
mapped_mask = cls._map_generic(mask)
return super(Ace, cls).__new__(cls, ace_type, flags,
mask, mapped_mask, sid, trustee)
@staticmethod
def _map_generic(mask):
if mask & GENERIC_READ:
mask = (mask & ~GENERIC_READ) | FILE_GENERIC_READ
if mask & GENERIC_WRITE:
mask = (mask & ~GENERIC_WRITE) | FILE_GENERIC_WRITE
if mask & GENERIC_EXECUTE:
mask = (mask & ~GENERIC_EXECUTE) | FILE_GENERIC_EXECUTE
if mask & GENERIC_ALL:
mask = (mask & ~GENERIC_ALL) | FILE_ALL_ACCESS
return mask
def inherited(self): # I
return bool(self.flags & INHERITED_ACE)
def object_inherit(self): # OI
return bool(self.flags & OBJECT_INHERIT_ACE)
def container_inherit(self): # CI
return bool(self.flags & CONTAINER_INHERIT_ACE)
def inherit_only(self): # IO
return bool(self.flags & INHERIT_ONLY_ACE)
def no_propagate(self): # NP
return bool(self.flags & NO_PROPAGATE_INHERIT_ACE)
def no_access(self): # N
return self.mapped_mask == 0
def full_access(self): # F
return self.mapped_mask == FILE_ALL_ACCESS
def modify_access(self): # M
return self.mapped_mask == FILE_MODIIFY_ACCESS
def read_exec_access(self): # RX
return self.mapped_mask == FILE_READ_EXEC_ACCESS
def read_only_access(self): # R
return self.mapped_mask == FILE_GENERIC_READ
def write_only_access(self): # W
return self.mapped_mask == FILE_GENERIC_WRITE
def delete_access(self): # D
return self.mapped_mask == FILE_DELETE_ACCESS
def get_file_rights(self):
if self.no_access(): return ['N']
if self.full_access(): return ['F']
if self.modify_access(): return ['M']
if self.read_exec_access(): return ['RX']
if self.read_only_access(): return ['R']
if self.write_only_access(): return ['W']
if self.delete_access(): return ['D']
rights = []
for right, name in ((DELETE, 'DE'), (READ_CONTROL, 'RC'),
(WRITE_DAC, 'WDAC'), (WRITE_OWNER, 'WO'),
(SYNCHRONIZE, 'S'),
(ACCESS_SYSTEM_SECURITY, 'AS'),
(GENERIC_READ, 'GR'), (GENERIC_WRITE, 'GW'),
(GENERIC_EXECUTE, 'GE'), (GENERIC_ALL, 'GA'),
(FILE_READ_DATA, 'RD'), (FILE_WRITE_DATA, 'WD'),
(FILE_APPEND_DATA, 'AD'), (FILE_READ_EA, 'REA'),
(FILE_WRITE_EA, 'WEA'), (FILE_EXECUTE, 'X'),
(FILE_DELETE_CHILD, 'DC'),
(FILE_READ_ATTRIBUTES, 'RA'),
(FILE_WRITE_ATTRIBUTES, 'WA')):
if self.mask & right:
rights.append(name)
return rights
def granted_access(self, mask):
return bool(self.mapped_mask & self._map_generic(mask))
def __str__(self):
trustee = self.trustee if self.trustee else self.sid
access = []
if self.ace_type == ACCESS_DENIED_ACE_TYPE:
access.append('(DENY)')
elif self.ace_type == SYSTEM_AUDIT_ACE_TYPE:
access.append('(AUDIT)')
if self.inherited(): access.append('(I)')
if self.object_inherit(): access.append('(OI)')
if self.container_inherit(): access.append('(CI)')
if self.inherit_only(): access.append('(IO)')
if self.no_propagate(): acccess.append('(NP)')
access.append('(%s)' % ','.join(self.get_file_rights()))
return '%s:%s' % (trustee, ''.join(access))
_FileSecurity = collections.namedtuple('_FileSecurity',
'path owner_permissions owner group '
'owner_sid group_sid flags dacl sacl')
class FileSecurity(_FileSecurity):
def __str__(self):
owner = self.owner if self.owner else self.owner_sid
group = self.group if self.group else self.group_sid
items = ['Path: %s' % self.path,
'Owner: %s' % owner,
'Group: %s' % group]
if self.dacl:
items += ['DACL: %s' %
'\n '.join(str(x) for x in self.dacl)]
if self.sacl:
items += ['SACL: %s' %
'\n '.join(str(x) for x in self.sacl)]
return '\n'.join(items)
函数
def list_acl(wmi_acl):
acl = []
for entry in wmi_acl:
trustee = entry.Trustee.Name
if trustee and entry.Trustee.Domain:
trustee = '%s\%s' % (entry.Trustee.Domain, trustee)
mask = entry.AccessMask
if mask < 0:
mask += 2 ** 32
ace = Ace(entry.AceType, entry.AceFlags, mask,
entry.Trustee.SIDString, trustee)
acl.append(ace)
return acl
# Win32_LogicalFileSecuritySetting
# https://msdn.microsoft.com/en-us/library/aa394180
WQL_LFSS = 'SELECT * FROM Win32_LogicalFileSecuritySetting WHERE Path="%s"'
wmi_ns = wmi.WMI()
def get_file_security(path):
path = os.path.abspath(path)
os.stat(path) # ensure path exists
lfss = wmi_ns.query(WQL_LFSS % (path,))[0]
sd = lfss.GetSecurityDescriptor()[0]
owner = sd.Owner.Name
if owner and sd.Owner.Domain:
owner = '%s\%s' % (sd.Owner.Domain, owner)
group = sd.Group.Name
if group and sd.Group.Domain:
group = '%s\%s' % (sd.Group.Domain, group)
dacl = sacl = ()
if sd.ControlFlags & SE_DACL_PRESENT:
dacl = tuple(list_acl(sd.DACL))
if sd.ControlFlags & SE_SACL_PRESENT:
sacl = tuple(list_acl(sd.SACL))
return FileSecurity(lfss.Path,
lfss.OwnerPermissions,
owner, group,
sd.Owner.SIDString,
sd.Group.SIDString,
sd.ControlFlags,
dacl, sacl)
访问 SACL 需要 SeSecurityPrivilege
。这是一些启用特权的 ctypes 代码:
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
advapi32 = ctypes.WinDLL('advapi32', use_last_error=True)
ERROR_NOT_ALL_ASSIGNED = 0x0514
SE_PRIVILEGE_ENABLED = 0x00000002
TOKEN_ALL_ACCESS = 0x000F0000 | 0x01FF
class LUID(ctypes.Structure):
_fields_ = (('LowPart', wintypes.DWORD),
('HighPart', wintypes.LONG))
class LUID_AND_ATTRIBUTES(ctypes.Structure):
_fields_ = (('Luid', LUID),
('Attributes', wintypes.DWORD))
class TOKEN_PRIVILEGES(ctypes.Structure):
_fields_ = (('PrivilegeCount', wintypes.DWORD),
('Privileges', LUID_AND_ATTRIBUTES * 1))
def __init__(self, PrivilegeCount=1, *args):
super(TOKEN_PRIVILEGES, self).__init__(PrivilegeCount, *args)
PDWORD = ctypes.POINTER(wintypes.DWORD)
PHANDLE = ctypes.POINTER(wintypes.HANDLE)
PLUID = ctypes.POINTER(LUID)
PTOKEN_PRIVILEGES = ctypes.POINTER(TOKEN_PRIVILEGES)
def errcheck_bool(result, func, args):
if not result:
raise ctypes.WinError(ctypes.get_last_error())
return args
kernel32.CloseHandle.argtypes = (wintypes.HANDLE,)
kernel32.GetCurrentProcess.errcheck = errcheck_bool
kernel32.GetCurrentProcess.restype = wintypes.HANDLE
# https://msdn.microsoft.com/en-us/library/aa379295
advapi32.OpenProcessToken.errcheck = errcheck_bool
advapi32.OpenProcessToken.argtypes = (
wintypes.HANDLE, # _In_ ProcessHandle
wintypes.DWORD, # _In_ DesiredAccess
PHANDLE) # _Out_ TokenHandle
# https://msdn.microsoft.com/en-us/library/aa379180
advapi32.LookupPrivilegeValueW.errcheck = errcheck_bool
advapi32.LookupPrivilegeValueW.argtypes = (
wintypes.LPCWSTR, # _In_opt_ lpSystemName
wintypes.LPCWSTR, # _In_ lpName
PLUID) # _Out_ lpLuid
# https://msdn.microsoft.com/en-us/library/aa375202
advapi32.AdjustTokenPrivileges.errcheck = errcheck_bool
advapi32.AdjustTokenPrivileges.argtypes = (
wintypes.HANDLE, # _In_ TokenHandle
wintypes.BOOL, # _In_ DisableAllPrivileges
PTOKEN_PRIVILEGES, # _In_opt_ NewState
wintypes.DWORD, # _In_ BufferLength
PTOKEN_PRIVILEGES, # _Out_opt_ PreviousState
PDWORD) # _Out_opt_ ReturnLength
def enable_privilege(privilege):
hToken = wintypes.HANDLE()
luid = LUID()
tp = TOKEN_PRIVILEGES()
advapi32.LookupPrivilegeValueW(None, privilege, ctypes.byref(luid))
tp.Privileges[0].Luid = luid
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED
advapi32.OpenProcessToken(kernel32.GetCurrentProcess(),
TOKEN_ALL_ACCESS,
ctypes.byref(hToken))
try:
advapi32.AdjustTokenPrivileges(hToken, False,
ctypes.byref(tp),
ctypes.sizeof(tp),
None, None)
if ctypes.get_last_error() == ERROR_NOT_ALL_ASSIGNED:
raise ctypes.WinError(ERROR_NOT_ALL_ASSIGNED)
finally:
kernel32.CloseHandle(hToken)
def disable_privilege(privilege):
hToken = wintypes.HANDLE()
luid = LUID()
tp = TOKEN_PRIVILEGES()
advapi32.LookupPrivilegeValueW(None, privilege, ctypes.byref(luid))
tp.Privileges[0].Luid = luid
tp.Privileges[0].Attributes = 0
advapi32.OpenProcessToken(kernel32.GetCurrentProcess(),
TOKEN_ALL_ACCESS,
ctypes.byref(hToken))
try:
advapi32.AdjustTokenPrivileges(hToken, False,
ctypes.byref(tp),
ctypes.sizeof(tp),
None, None)
if ctypes.get_last_error() == ERROR_NOT_ALL_ASSIGNED:
raise ctypes.WinError(ERROR_NOT_ALL_ASSIGNED)
finally:
kernel32.CloseHandle(hToken)
例如,我向 "Program Files" 目录添加了审计 ACE,以记录任何人更改目录权限或所有者的任何尝试。此 ACE 类型存储在系统访问控制列表 (SACL) 中。
>>> enable_privilege('SeSecurityPrivilege')
>>> print get_file_security('C:\Program Files')
Path : C:\Program Files
Owner: NT SERVICE\TrustedInstaller
Group: NT SERVICE\TrustedInstaller
DACL : NT SERVICE\TrustedInstaller:(F)
NT SERVICE\TrustedInstaller:(CI)(IO)(F)
NT AUTHORITY\SYSTEM:(M)
NT AUTHORITY\SYSTEM:(OI)(CI)(IO)(F)
BUILTIN\Administrators:(M)
BUILTIN\Administrators:(OI)(CI)(IO)(F)
BUILTIN\Users:(RX)
BUILTIN\Users:(OI)(CI)(IO)(RX)
CREATOR OWNER:(OI)(CI)(IO)(F)
APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES:(RX)
APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES:(OI)(CI)(IO)(RX)
SACL : Everyone:(AUDIT)(WDAC,WO)
下面显示了拒绝 ACE 是如何出现的:
>>> f = open('tempfile', 'w'); f.close()
>>> os.system('icacls tempfile /deny Guests:(M)')
processed file: tempfile
Successfully processed 1 files; Failed processing 0 files
0
>>> print get_file_security('tempfile')
Path : C:\Temp\tempfile
Owner: BUILTIN\Administrators
Group: THISPC\None
DACL : BUILTIN\Guests:(DENY)(M)
BUILTIN\Administrators:(I)(F)
NT AUTHORITY\SYSTEM:(I)(F)
BUILTIN\Users:(I)(RX)
NT AUTHORITY\Authenticated Users:(I)(M)