尽管是文件所有者,但READ_CONTROL的CreateFileW失败,并显示“访问被拒绝”

时间:2019-10-15 11:01:11

标签: python windows acl pywin32 dacl

在Windows上,即使任意ACL(DACL)为空,即没有人对该文件具有权限,文件所有者也可以读写DACL(READ_CONTROLWRITE_DAC访问权限)。

所以我尝试执行以下操作:

  1. 在文件上设置一个空的DACL
  2. 获取READ_CONTROL的文件句柄
  3. 使用GetSecurityInfo和句柄获取安全描述符
  4. 检查DACL是否为空

但是,使用CreateFileW获取句柄失败,错误为Access is denied。令人惊讶的是,GetFileSecurity(相当于文件的GetSecurityInfo)工作正常。 根据{{​​3}},GetFileSecurity需要READ_CONTROL访问。

在以下示例中,CreateFileW为什么会失败?

import sys
import win32security
import win32con
import win32file
import ntsecuritycon
import os

path = sys.argv[1]

with open(path, "w"):
    pass  # I am the owner of the file

print("Set empty ACL")
sd = win32security.GetFileSecurity(path, win32security.DACL_SECURITY_INFORMATION)
dacl = win32security.ACL()
sd.SetSecurityDescriptorDacl(1, dacl, 0)
win32security.SetFileSecurity(path, win32security.DACL_SECURITY_INFORMATION, sd)

try:
    print("Ensure that ACL is empty with GetFileSecurity")
    sd = win32security.GetFileSecurity(path, win32security.DACL_SECURITY_INFORMATION)
    dacl = sd.GetSecurityDescriptorDacl()
    assert 0 == dacl.GetAceCount()

    print("Try to ensure that ACL is empty using handle")
    handle = win32file.CreateFileW(
        path,
        ntsecuritycon.READ_CONTROL,
        0,
        None,  # security attributes
        win32con.OPEN_EXISTING,
        0,
        None,
    )
    sd = win32security.GetSecurityInfo(handle, win32security.SE_FILE_OBJECT, win32security.DACL_SECURITY_INFORMATION)
    dacl = sd.GetSecurityDescriptorDacl()
    assert 0 == dacl.GetAceCount()
except Exception as e:
    print("FAILURE:", e)
finally:
    print("Restore inherited ACEs before removing file")
    dacl = win32security.ACL()
    win32security.SetNamedSecurityInfo(
        path, 
        win32security.SE_FILE_OBJECT, 
        win32security.DACL_SECURITY_INFORMATION,
        None,
        None,
        dacl,
        None
    )
    os.unlink(path)

输出:

> python acl-test.py file
Set empty ACL
Ensure that ACL is empty with GetFileSecurity
Try to ensure that ACL is empty using handle
FAILURE: (5, 'CreateFileW', 'Access is denied.')
Restore inherited ACEs before removing file

1 个答案:

答案 0 :(得分:2)

CreateFileW内部调用NtCreateFile,并且将DesiredAccess参数传递为dwDesiredAccess | FILE_READ_ATTRIBUTES | SYNCHRONIZE。因此,如果您将dwDesiredAccess作为READ_CONTROL传递,那么它实际上会尝试以READ_CONTROL | FILE_READ_ATTRIBUTES | SYNCHRONIZE访问权限打开文件。如果调用方具有对父文件夹的FILE_READ_ATTRIBUTES访问权限,则文件系统隐式授予FILE_LIST_DIRECTORY访问权限。但是,如果文件具有空的DACL,则将不授予SYNCHRONIZE访问权限。

这里的一种解决方案是使用NtOpenFileNtCreateFile来控制确切的请求访问权限。