确定是否继承了ntfs权限的可靠方法

时间:2009-05-26 13:31:30

标签: python winapi acl ntfs file-permissions

我在这里有一个有点模糊的问题。

我需要:确定是否继承了文件/文件夹的权限(或严格来说,DACL的特定ACE)。

我是如何解决这个问题的:使用winapi绑定python(确切地说是win32security模块)。这是精简版本,它就是这样做的 - 它只是将一个文件路径作为参数,逐个打印出ACE,表明设置了哪些标志。

#!/usr/bin/env python
from win32security import *
import sys

def decode_flags(flags):
    _flags = {
        SE_DACL_PROTECTED:"SE_DACL_PROTECTED",
        SE_DACL_AUTO_INHERITED:"SE_DACL_AUTO_INHERITED",
        OBJECT_INHERIT_ACE:"OBJECT_INHERIT_ACE",
        CONTAINER_INHERIT_ACE:"CONTAINER_INHERIT_ACE",
        INHERIT_ONLY_ACE:"INHERIT_ONLY_ACE",
        NO_INHERITANCE:"NO_INHERITANCE",
        NO_PROPAGATE_INHERIT_ACE:"NO_PROPAGATE_INHERIT_ACE",
        INHERITED_ACE:"INHERITED_ACE"
    }
    for key in _flags.keys():
        if (flags & key):
            print '\t','\t',_flags[key],"is set!"


def main(argv):
    target = argv[0]
    print target

    security_descriptor = GetFileSecurity(target,DACL_SECURITY_INFORMATION)

    dacl = security_descriptor.GetSecurityDescriptorDacl()

    for ace_index in range(dacl.GetAceCount()):
        (ace_type,ace_flags),access_mask,sid = dacl.GetAce(ace_index)
        name,domain,account_type = LookupAccountSid(None,sid)
        print '\t',domain+'\\'+name,hex(ace_flags)
        decode_flags(ace_flags)


if __name__ == '__main__':
    main(sys.argv[1:])

足够简单 - 获取安全描述符,从中获取DACL,然后遍历DACL中的ACE。这里真正重要的是INHERITED_ACE访问标志。它应该在继承ACE时设置,而不是显式设置。

创建文件夹/文件时,其ACL将根据父对象(文件夹)的ACE填充ACE,这些ACE设置为传播给子项。但是,除非您对访问列表进行任何更改,否则将不会设置INHERITED_ACE标志!但继承的权限在那里,他们可以工作。

如果你做了任何细微的改变(比如,在访问列表中添加一个条目,应用更改并将其删除),那么标志就会神奇地出现(行为不会以任何方式改变,但之前有效,之后可以使用) )!我想要的是找到INHERITED_ACE标志的这种行为的来源,并且可能找到另一种可靠的方式来确定ACE是否被继承。

如何重现:

  1. 创建对象(文件或文件夹)
  2. 检查Windows资源管理器中的权限,查看它们是否已从父对象传播(例如,使用Windows资源管理器的文件属性对话框的安全选项卡)。
  3. 使用例如我正在使用的脚本检查标志(不会在任何ACE上设置INHERITED_ACE)。
  4. 更改对象的权限(应用更改),甚至更改它们。
  5. 检查标志(INHERITED_ACE 在那里)
  6. ..难以置信地摇头(我知道我做了)
  7. 对于有点冗长的帖子感到抱歉,希望这至少有点意义。

3 个答案:

答案 0 :(得分:1)

您可以使用.Net框架

System.Security.AccessControl

这包括ACL和DACL以及SACL。

答案 1 :(得分:1)

我认为原始海报是在

中看到详细的行为

This newsgroup posting

请注意,容器上设置的控制标志只需通过取消勾选并重新勾选GUI中的继承框即可更改。

进一步注意,使用Microsoft工具简单地向DACL添加ACE也会改变控制标志。

进一步注意,由于新闻组帖子中讨论过许多微妙的错误,因此在继承时不能依赖GUI,cacls和icacls。

似乎控制继承的“旧”方法是使用容器上的控制标志和继承相关的ACE标志。

“new”方式不使用容器上的控制标志,而是使用重复的ACE;一个用于控制对象的访问,另一个用于控制子对象继承的内容。

但是,现有的Microsoft工具(例如Vista)似乎无法以“新”方式工作,因此当您使用这些工具进行简单更改时,它会采用旧的方式在容器上使用控制标志

如果你在Vista上创建一个新分区,然后创建一个新文件夹,然后查看标志和ACE,它将看起来像这样

ControlFlags : 0x8004
Owner : BUILTIN\Administrators
Group : WS1\None
S-1-5-32-544 : BUILTIN\Administrators : 0x0 : 0x0 : 0x1F01FF
S-1-5-32-544 : BUILTIN\Administrators : 0x0 : 0xB : 0x10000000
S-1-5-18 : NT AUTHORITY\SYSTEM : 0x0 : 0x0 : 0x1F01FF
S-1-5-18 : NT AUTHORITY\SYSTEM : 0x0 : 0xB : 0x10000000
S-1-5-11 : NT AUTHORITY\Authenticated Users : 0x0 : 0x0 : 0x1301BF
S-1-5-11 : NT AUTHORITY\Authenticated Users : 0x0 : 0xB : 0xE0010000
S-1-5-32-545 : BUILTIN\Users : 0x0 : 0x0 : 0x1200A9
S-1-5-32-545 : BUILTIN\Users : 0x0 : 0xB : 0xA0000000

请注意ControlFlags和重复的ACE。

答案 2 :(得分:0)

在我的Win XP Home Edition上,这段代码似乎根本不起作用: - )

我得到了这个堆栈跟踪:

  

追踪(最近的呼叫最后):
  文件“C:\ 1.py”,第37行,in       主(sys.argv中[1:])
  文件“C:\ 1.py”,第29行,在main中       对于范围内的ace_index(dacl.GetAceCount()):

     

AttributeError:'NoneType'对象没有属性'GetAceCount'

你能尝试“轻推”DACL吗? 我的意思是,如果你知道它在你做了一些细微的改变之后会起作用...以编程方式做一些改变,添加一个存根ACE并将其删除。你能吗?

UPDATE。我在我的工作机器上使用C#程序进行了实验(使用Win XP Prof),我必须告诉您.net获取此安全信息的方式确实有效。因此,当我创建一个新文件时,我的C#程序检测到ACE是继承的,而你的python代码则没有。

以下是我的跑步的示例输出:

  

C:> csharp_tricks.exe 2.txt

     

FullControl - > IsInherited:True

     

FullControl - > IsInherited:True

     

ReadAndExecute,Synchronize - > IsInherited:True

     
     

C:> 1.py 2.txt

     

2.txt

     

BUILTIN \ Administrators 0x0

     

NT AUTHORITY \ SYSTEM 0x0

     

BUILTIN \ Users 0x0

我的C#课程:

public class InheritedAce
{
    public static string GetDACLReport(string path)
    {
        StringBuilder result = new StringBuilder();
        FileSecurity fs = new FileSecurity(path, AccessControlSections.Access);
        foreach (var rule in fs.GetAccessRules(true, true, typeof(SecurityIdentifier)).OfType<FileSystemAccessRule>())
        {
            result.AppendFormat("{0}  -->  IsInherited:  {1}", rule.FileSystemRights, rule.IsInherited);
            result.AppendLine();
        }

        return result.ToString();
    }
}

所以,它似乎是python pywin32安全库中的一个错误。也许他们没有做所有必要的系统调用......