9

我正在努力克服以下情况。

给定一个存储在 NTFS 卷上的目录,其中:

  1. 目录所有者设置为其他人(例如非特权用户)
  2. 目录 DACL 配置为允许访问不包括系统或管理员的特定人群
  3. 目录上的 DACL 实际上不授予任何人获取所有权或更改 DACL 的访问权限

(或者简而言之,所有管理员都被锁定在文件夹之外)

但!

  1. 我运行的帐户具有管理权限(SeBackupPrivilege、SeSecurityPrivilege)
  2. 现有的 DACL 可以忽略,因为我正在写一个新的
  3. 使用其他工具(takeown.exe),我可以访问相关目录。

(或者简而言之,我有权修复 DACL/所有者)

我应该对以下代码没有问题:

WindowsIdentity privilegedUser = System.Security.Principal.WindowsIdentity.GetCurrent();

// I cannot use File.GetAccessControl() as I get access denied
// (working as intended! I have no access to read the ACL!)
// so I have to write a new ACL:
FileSecurity acl = new FileSecurity();
acl.SetOwner(admin.User);
acl.AddAccessRule(new FileSystemAccessRule(privilegedUser.User, FileSystemRights.FullControl, AccessControlType.Allow));

File.SetAccessControl("c:\\path\\to\\broken", acl);

但是,SetAccessControl调用会引发UnauthorizedAccessException。当我将其更改为仅调整所有者时,会发生同样的事情。当我只尝试调整 DACL 时,同样的事情。

我通过在 Process Explorer 中检查生成的进程来验证问题不是 UAC,并验证管理员组设置为“所有者”而不是“禁用”。我应该拥有执行此操作的所有必要权限(备份操作员在管理员面前应该是无关紧要的,但我添加它是为了测试)——但它只是不断抛出访问被拒绝。

相关技术网文档:http ://technet.microsoft.com/en-us/library/cc783530%28WS.10%29.aspx

  • “如果您拥有一个对象,您可以授予任何用户或安全组对该对象的任何权限,包括获得所有权的权限。”
  • 所有权可以通过以下方式转让:
    • 当前所有者可以将“取得所有权”权限授予其他用户,允许该用户随时取得所有权。用户必须实际取得所有权才能完成转移。(不幸的是,在这种情况下,所有者不能重新分配所有权。)
    • 管理员可以取得所有权。
    • 具有还原文件和目录用户权限的用户可以将所有权分配给任何用户或组。
  • 获得文件和其他对象所有权的能力是另一种情况,其中管理员维护系统的需要优先于所有者控制访问的权利。通常,只有当对象的当前所有者允许您这样做时,您才能获得对象的所有权。NTFS 对象的所有者可以通过授予另一个用户 Take Ownership 权限来允许另一个用户取得所有权;Active Directory 对象的所有者可以授予另一个用户修改所有者权限。拥有此权限的用户可以在没有当前所有者许可的情况下取得对象的所有权。默认情况下,该权限仅分配给内置管理员组。当当前所有者不再可用时,管理员通常使用它来获取和重新分配资源的所有权。

我在这里想念什么?

4

2 回答 2

7

我遇到了同样的问题,只是在这里为可能像我一样来这里搜索的其他人发帖:

您需要在代码中显式启用 SeTakeOwnershipPrivilege。我发现Process Privileges对处理这类事情非常有帮助。

这是它修复我的代码的方法(似乎出于某种原因,即使我有特权,除非我明确启用它,否则该过程不会):

using (new ProcessPrivileges.PrivilegeEnabler(Process.GetCurrentProcess(), Privilege.TakeOwnership))
{
    directoryInfo = new DirectoryInfo(path);
    directorySecurity = directoryInfo.GetAccessControl();

    directorySecurity.SetOwner(WindowsIdentity.GetCurrent().User);
    Directory.SetAccessControl(path, directorySecurity);    
}

PS:谢谢西蒙..您的回答给了我一个起点。

于 2011-05-20T16:09:44.347 回答
6

在添加访问权限之前,您需要取得所有权。

using (var user = WindowsIdentity.GetCurrent())
{
    var ownerSecurity = new FileSecurity();
    ownerSecurity.SetOwner(user.User);
    File.SetAccessControl("c:\\path\\to\\broken", ownerSecurity);

    var accessSecurity = new FileSecurity();
    accessSecurity.AddAccessRule(new FileSystemAccessRule(user.User, FileSystemRights.FullControl, AccessControlType.Allow));
    File.SetAccessControl("c:\\path\\to\\broken", accessSecurity);
}

此外,如果您正在设置 DirectorySecurity,您将需要这个

using (var user = WindowsIdentity.GetCurrent())
{
    var ownerSecurity = new DirectorySecurity();
    ownerSecurity.SetOwner(user.User);
    Directory.SetAccessControl("c:\\path\\to\\broken", ownerSecurity);

    var accessSecurity = new DirectorySecurity();
    accessSecurity.AddAccessRule(new FileSystemAccessRule(user.User, FileSystemRights.FullControl, AccessControlType.Allow));
    Directory.SetAccessControl("c:\\path\\to\\broken", accessSecurity);
}

如果这不起作用试试这个

http://blog.mikeobrien.net/2009/11/taking-ownership-and-setting-admin.html

于 2011-03-28T04:44:59.697 回答