确定是不是继承了 ntfs 权限的可靠方法
Posted
技术标签:
【中文标题】确定是不是继承了 ntfs 权限的可靠方法【英文标题】:A reliable way to determine if ntfs permissions were inherited确定是否继承了 ntfs 权限的可靠方法 【发布时间】:2010-10-28 23:35:57 【问题描述】:我在这里有一个有点模糊的问题。
我需要什么:确定文件/文件夹的权限(或者,严格来说,DACL 的特定 ACE)是否被继承。
我如何尝试解决这个问题:使用 python 的 winapi 绑定(准确地说是 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 是否被继承。
如何重现:
-
创建对象(文件或文件夹)
在 Windows 资源管理器中检查权限,查看它们是否已从父对象传播(例如,使用 Windows 资源管理器的文件属性对话框的安全选项卡)。
使用例如我使用的脚本检查标志(INHERITED_ACE 不会在任何 ACE 上设置)。
更改对象的权限(应用更改),甚至将它们改回来。
检查标志(INHERITED_ACE 将在那里)
..难以置信地摇头(我知道我做到了)
抱歉,这篇文章有点冗长,希望这至少有点意义。
【问题讨论】:
我已经更新了我的答案。这似乎是 Python 库的问题... 【参考方案1】:你可以使用.Net框架
System.Security.AccessControl
这包括 ACL 和 DACL 和 SACL。
【讨论】:
不幸的是,使用 .Net 是不可能的。无论哪种方式,在检查 System.Security.AccessControl 上的 msdn 条目后,我得出的结论是,从本质上讲,它没有提供超过 C API 的附加功能(至少在我感兴趣的领域没有),-我的问题是不是关于如何检索继承标志, - 这是微不足道的,而是关于 INHERITED_ACE 标志的不一致。【参考方案2】:在我的 Win XP Home Edition 上,此代码似乎根本不起作用 :-)
我得到了这个堆栈跟踪:
回溯(最近一次通话最后一次): 文件“C:\1.py”,第 37 行,在 主要(sys.argv[1:]) 文件“C:\1.py”,第 29 行,在 main 对于范围内的 ace_index(dacl.GetAceCount()):
AttributeError: 'NoneType' 对象没有属性 'GetAceCount'
您可以尝试“轻推”要填充的 DACL 吗? 我的意思是,如果您知道它会在您对其进行轻微更改后工作......以编程方式进行轻微更改,添加一个存根 ACE 并将其删除。可以吗?
更新。我在我的工作机器(使用 Win XP Prof)上做了一个 C# 程序的实验,我必须告诉你,获取此安全信息的 .net 方法确实有效。因此,当我创建一个新文件时,我的 C# 程序会检测到 ACE 已被继承,而您的 python 代码却没有。
这是我运行的示例输出:
C:>csharp_tricks.exe 2.txt
FullControl --> IsInherited: True
FullControl --> IsInherited: True
ReadAndExecute,同步 --> IsInherited: True
C:>1.py 2.txt
2.txt
BUILTIN\Administrators 0x0
NT AUTHORITY\SYSTEM 0x0
内置\用户 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 安全库中的一个错误。也许他们没有做所有必要的系统调用......
【讨论】:
是的,这在家庭版中肯定行不通——据我所知,ntfs 权限在那里被禁用(所以你得到 None 作为 GetSecurityDescriptorDacl 的结果)。您的建议也许是正确的,我应该只使用存根 ACE 来修复 DACL。但是,考虑一个事实,即我需要在一个巨大的公司文件服务器上运行这种代码(想想,数百万个对象)。如果我(或你)的假设是错误的怎么办?如果事情搞砸了怎么办?除非绝对不可避免,否则我不会对此类数据执行写入操作。 我不敢相信您的回答实际上被某人否决了。无论如何,非常感谢您的努力。我无法检查您的建议是否正确(没有环境),但是对我来说它看起来很可靠。我将通过对照父对象访问列表检查 ACE 来解决这个问题。感谢您的努力,您获得了这份赏金 :) 好吧,ACE 可以只复制到子节点,而不是继承...但是如果它适合您的需要,我认为没有问题 :-) 不过,有了这些证明,您可能会提交一个错误到python开发... @shylent:NTFS 权限在 XP Home Edition 中没有被禁用,我上次检查过——只有用于查看/设置它们的 GUI 内容。cacls
等将查看和设置权限就好了,内核将强制执行它们。【参考方案3】:
我认为原始发布者看到了
中详述的行为This newsgroup posting
请注意,容器上设置的控制标志可以通过在 GUI 中取消勾选和重新勾选继承框来更改。
进一步注意,使用 Microsoft 的工具简单地将 ACE 添加到 DACL 也会更改控制标志。
进一步注意,由于新闻组发布中讨论的许多细微错误,在继承方面不能依赖 GUI、cacls 和 icacls。
似乎控制继承的“旧”方式是结合使用容器上的控制标志和与继承相关的 ACE 标志。
“新”方式不使用容器上的控制标志,而是使用重复的 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。
【讨论】:
以上是关于确定是不是继承了 ntfs 权限的可靠方法的主要内容,如果未能解决你的问题,请参考以下文章