2016-01-09 104 views

回答

2

這是WMI使用Tim Golden的例子wmi module。它爲給定的路徑選擇一個Win32_LogicalFileSecuritySetting的實例。它調用GetSecurityDescriptor方法得到Win32_SecurityDescriptor。我用這個來創建AceFileSecurity命名的多個實例。我已經添加了一些方法來測試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的代碼以使特權:

​​

例如,我添加了一個審計ACE到「Program Files」目錄記錄不會有任何人試圖改變目錄的權限或所有者。此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) 
+0

謝謝。但是有沒有簡單的方法可以做到這一點?這個例子對於這樣一個簡單的任務看起來相當複雜 –

+0

如果你正在編寫一個程序來從頭開始,使用wmi是最簡單的方法。我本來可以通過ctypes使用Windows API來完成所有的工作,但是這會更長。如果你只是想要文本輸出,使用子進程調用icacls.exe並轉儲DACL將會簡單很多,但是(1)通常不是很有用,(2)它是Stack Overflow的主題;這是[超級用戶](http://superuser.com)的主題。 – eryksun