SeBackupPrivilege
使系统授予对任何文件的所有读取访问控制,而不管为该文件指定的访问控制列表(ACL)。 ACL仍会评估除读取以外的任何访问请求。如果拥有此特权,则授予以下访问权限:READ_CONTROL,ACCESS_SYSTEM_SECURITY,FILE_GENERIC_READ,FILE_TRAVERSE
SeRestorePrivilege:
使系统授予对任何文件的所有写访问控制,而不管为该文件指定的ACL。除写入外,其他访问请求仍将通过ACL进行评估。如果拥有此特权,则授予以下访问权限:WRITE_DAC,WRITE_OWNER,ACCESS_SYSTEM_SECURITY,FILE_GENERIC_WRITE,FILE_ADD_FILE,FILE_ADD_SUBDIRECTORY,DELETE
但是,我注意到,如果进程令牌具有SeRestorePrivilege,则成功打开READ_CONTROL
文件。为什么会这样?
代码:
import os
import sys
import ntsecuritycon
import win32con
import win32file
import win32security
import win32api
def print_token_info():
tok = win32security.OpenProcessToken(win32api.GetCurrentProcess(), win32security.TOKEN_QUERY)
sid, attr = win32security.GetTokenInformation(tok, win32security.TokenUser)
name, domain, sid_name_use = win32security.LookupAccountSid(None, sid)
print(f"User: {name}@{domain}")
sid = win32security.GetTokenInformation(tok, win32security.TokenOwner)
name, domain, sid_name_use = win32security.LookupAccountSid(None, sid)
print(f"Owner of new files: {name}@{domain}")
privileges = win32security.GetTokenInformation(tok, win32security.TokenPrivileges)
print("Privileges")
priv_attr_flags = {
win32security.SE_PRIVILEGE_ENABLED: 'SE_PRIVILEGE_ENABLED',
win32security.SE_PRIVILEGE_ENABLED_BY_DEFAULT: 'SE_PRIVILEGE_ENABLED_BY_DEFAULT',
win32security.SE_PRIVILEGE_REMOVED: 'SE_PRIVILEGE_REMOVED',
win32security.SE_PRIVILEGE_USED_FOR_ACCESS: 'SE_PRIVILEGE_USED_FOR_ACCESS',
}
for luid, attr in privileges:
priv_name = win32security.LookupPrivilegeName(None, luid)
flag_str = []
for flag in priv_attr_flags:
if (attr & flag) == flag:
flag_str.append(priv_attr_flags[flag])
print(f"- {priv_name} -> {attr} ({', '.join(flag_str)})")
win32api.CloseHandle(tok)
def disable_privilege(privilege_name):
print(f"Disabling privilege {privilege_name}")
tok = win32security.OpenProcessToken(
win32api.GetCurrentProcess(), win32security.TOKEN_ADJUST_PRIVILEGES | win32security.TOKEN_QUERY
)
luid = win32security.LookupPrivilegeValue(None, privilege_name)
se_privilege_disabled = 0
new_state = [(luid, se_privilege_disabled)]
win32security.AdjustTokenPrivileges(tok, 0, new_state)
win32api.CloseHandle(tok)
def enable_privilege(privilege_name):
print(f"Enabling privilege {privilege_name}")
tok = win32security.OpenProcessToken(
win32api.GetCurrentProcess(), win32security.TOKEN_ADJUST_PRIVILEGES | win32security.TOKEN_QUERY
)
luid = win32security.LookupPrivilegeValue(None, privilege_name)
new_state = [(luid, win32security.SE_PRIVILEGE_ENABLED)]
win32security.AdjustTokenPrivileges(tok, 0, new_state)
win32api.CloseHandle(tok)
def open_handle(path):
try:
handle = win32file.CreateFileW(
path,
ntsecuritycon.READ_CONTROL,
0,
None,
win32con.OPEN_EXISTING,
win32file.FILE_FLAG_OPEN_REPARSE_POINT | win32file.FILE_FLAG_BACKUP_SEMANTICS,
None,
)
handle.Close()
print(f"Successfully opened {path}")
except Exception as e:
print(f"Failed to open {path}: {e}")
if __name__ == '__main__':
path = sys.argv[1]
with open(path, "w") as fo:
pass
dacl = win32security.ACL()
dacl.SetEntriesInAcl([])
win32security.SetNamedSecurityInfo(
path,
win32security.SE_FILE_OBJECT,
win32security.DACL_SECURITY_INFORMATION | win32security.PROTECTED_DACL_SECURITY_INFORMATION,
None,
None,
dacl,
None,
)
print_token_info()
open_handle(path)
print()
enable_privilege(win32security.SE_BACKUP_NAME)
# print_token_info()
open_handle(path)
print()
disable_privilege(win32security.SE_BACKUP_NAME)
# print_token_info()
open_handle(path)
print()
enable_privilege(win32security.SE_RESTORE_NAME)
# print_token_info()
open_handle(path)
print()
disable_privilege(win32security.SE_RESTORE_NAME)
# print_token_info()
open_handle(path)
print()
在高级控制台上的输出:
> python .\test_access.py C:\tmp\test\file-10
User: dev@CBIT-02
Owner of new files: Administrators@BUILTIN
Privileges
- SeIncreaseQuotaPrivilege -> 0 ()
- SeSecurityPrivilege -> 0 ()
- SeTakeOwnershipPrivilege -> 0 ()
- SeLoadDriverPrivilege -> 0 ()
- SeSystemProfilePrivilege -> 0 ()
- SeSystemtimePrivilege -> 0 ()
- SeProfileSingleProcessPrivilege -> 0 ()
- SeIncreaseBasePriorityPrivilege -> 0 ()
- SeCreatePagefilePrivilege -> 0 ()
- SeBackupPrivilege -> 0 ()
- SeRestorePrivilege -> 0 ()
- SeShutdownPrivilege -> 0 ()
- SeDebugPrivilege -> 2 (SE_PRIVILEGE_ENABLED)
- SeSystemEnvironmentPrivilege -> 0 ()
- SeChangeNotifyPrivilege -> 3 (SE_PRIVILEGE_ENABLED, SE_PRIVILEGE_ENABLED_BY_DEFAULT)
- SeRemoteShutdownPrivilege -> 0 ()
- SeUndockPrivilege -> 0 ()
- SeManageVolumePrivilege -> 0 ()
- SeImpersonatePrivilege -> 3 (SE_PRIVILEGE_ENABLED, SE_PRIVILEGE_ENABLED_BY_DEFAULT)
- SeCreateGlobalPrivilege -> 3 (SE_PRIVILEGE_ENABLED, SE_PRIVILEGE_ENABLED_BY_DEFAULT)
- SeIncreaseWorkingSetPrivilege -> 0 ()
- SeTimeZonePrivilege -> 0 ()
- SeCreateSymbolicLinkPrivilege -> 2 (SE_PRIVILEGE_ENABLED)
- SeDelegateSessionUserImpersonatePrivilege -> 0 ()
Failed to open C:\tmp\test\file-10: (5, 'CreateFileW', 'Access is denied.')
Enabling privilege SeBackupPrivilege
Successfully opened C:\tmp\test\file-10
Disabling privilege SeBackupPrivilege
Failed to open C:\tmp\test\file-10: (5, 'CreateFileW', 'Access is denied.')
Enabling privilege SeRestorePrivilege
Successfully opened C:\tmp\test\file-10
Disabling privilege SeRestorePrivilege
Failed to open C:\tmp\test\file-10: (5, 'CreateFileW', 'Access is denied.')
如问题中所述,具有备份语义的SeRestorePrivilege授予以下权限:ACCESS_SYSTEM_SECURITY
,WRITE_DAC
,WRITE_OWNER
,DELETE
,FILE_ADD_FILE
,FILE_ADD_SUBDIRECTORY
和FILE_GENERIC_WRITE
。
FILE_GENERIC_WRITE
是访问掩码,已映射到文件对象的GENERIC_WRITE
访问。它包括READ_CONTROL
,SYNCHRONIZE
,FILE_WRITE_ATTRIBUTES
(0x0100),FILE_WRITE_EA
(0x0010),FILE_APPEND_DATA
(0x0004)和FILE_WRITE_DATA
(0x0002)。请注意,后两个值与FILE_ADD_SUBDIRECTORY
(0x0004)和FILE_ADD_FILE
(0x0002)相同,因此SeRestorePrivilege的文档是多余的。
蒙版中的READ_CONTROL
来自STANDARD_RIGHTS_WRITE
。大多数通用访问掩码包括以下标准权限掩码之一:
STANDARD_RIGHTS_READ = READ_CONTROL
STANDARD_RIGHTS_WRITE = READ_CONTROL
STANDARD_RIGHTS_EXECUTE = READ_CONTROL
STANDARD_RIGHTS_REQUIRED = READ_CONTROL | WRITE_DAC | WRITE_OWNER | DELETE
以上全部包括READ_CONTROL
权限,该权限确保请求通用访问包括查询对象的自行决定性和强制性安全性的权利。
请注意,您的实验还需要控制隐式所有者权利。如果文件的所有者是发出请求的用户或用户的已启用组之一,则将隐式授予该用户READ_CONTROL
和WRITE_DAC
访问权限。您可以通过确保文件由不同的安全性原则(例如“ SYSTEM”)拥有,或通过为“ OWNER_RIGHTS”安全性原则添加一个不授予访问权限的ACE(覆盖隐式所有者权限)来进行控制。
也请注意,即使CreateFile
为0,SYNCHRONIZE
也会隐式请求FILE_READ_ATTRIBUTES
和dwDesiredAccess
访问。SeRestorePrivilege不授予FILE_READ_ATTRIBUTES
访问权限。在您的实验中,此权限必须已由文件系统策略授予。不管文件的安全描述符如何,如果用户具有对父目录的FILE_READ_DATA
(即FILE_LIST_DIRECTORY
)访问权限,则该用户将被授予读取属性的权限。这样可以使文件API保持一致,因为大多数文件元数据(例如文件属性,时间戳和大小)都可以通过列出父目录来获得。要控制实验,您需要使用不授予用户读取数据访问权限的子目录。然后,您将观察到SeRestorePrivilege本身并未启用CreateFile
成功。