如何在C#中编辑DACL?

时间:2018-06-20 15:52:01

标签: c# windows windows-security

我可以模拟SetFileSecurity function吗?

我是C#的新手。我需要从Python重新编写一些测试,因此,我被困在这一部分: 在Python中,我可以使用pywin32自由编辑DACL(这是具有C ++实现的模块,可以与Windows API一起使用)。 我可以使用win32security编辑任何ACE。

将所有者更改为所有人?好吧。

win32security.SetNamedSecurityInfo("somefile.txt", win32security.SE_FILE_OBJECT,
                                       win32security.OWNER_SECURITY_INFORMATION,
                                       win32security.ConvertStringSidToSid("S-1-1-0"))
sd.SetSecurityDescriptorDacl(1, dacl, 0)
win32security.SetFileSecurity(filename, win32security.DACL_SECURITY_INFORMATION, sd)

要删除继承的ACE之一?容易。

sd = win32security.GetFileSecurity("", win32security.DACL_SECURITY_INFORMATION)
dacl = SECURITY_DESCRIPTOR.GetSecurityDescriptorDacl()
dacl.DeleteAce(0)
sd.SetSecurityDescriptorDacl(1, dacl, 0)  # may not be necessary
win32security.SetFileSecurity(filename, win32security.DACL_SECURITY_INFORMATION, sd)

所有没有特殊权限的人。

但是,如果我想在C#中做类似的事情(我发现的一种方法是使用纯SDDL更改安全描述符),但是使用System.Security.File.SetAccessControl()的{​​{1}},则由FileSecurity定义没有特权SetSecutiryDesctiptorSddlForm,就无法工作。同样,即使具有几乎所有特权的管理员令牌,如果我想以“错误”的方式更改某些内容(删除一些继承的ACE),安全描述符也不适用。如果我尝试做“非常错误”的事情,例如将所有者设置为“所有人”,则会引发异常。

SeSecurityPrivelege

使用管理员令牌运行:

var sddl_everyone_owner = @"O:S-1-1-0G:DUD:P";
var path = @"C:\Users\someuser\test.txt";
FileSecurity fs_edit = new FileSecurity();
fs_edit.SetSecurityDescriptorSddlForm(sddl_everyone_owner);
File.SetAccessControl(path, fs_edit);

2 个答案:

答案 0 :(得分:0)

经过11个小时的谷歌搜索,然后尝试编写一些唤醒代码,我有这样的话:

// changes SDDL of file:
using System;
using System.Runtime.InteropServices; // DllImport

public class SomeClass
{
    [DllImport("Advapi32.dll", SetLastError = true)]
    static extern void SetFileSecurity(string path, int type_of_sd, IntPtr sd);
    [DllImport("Advapi32.dll", SetLastError = true)]
    static extern bool ConvertStringSecurityDescriptorToSecurityDescriptor(string StringSecurityDescriptor, uint StringSDRevision, out IntPtr SecurityDescriptor, out UIntPtr SecurityDescriptorSize);
    private static void Main()
    {
        string path = @"C:\Some\path\to\file";
        string sddl = "D:AI(A;ID;FA;;;S-1-1-0)"; // set only one ACE: inherited full access to Everyone
        uint sd_revision = 1;  // the only revision of SECURITY_DESCRIPTOR
        int DACL_SECURITY_INFORMATION = 4; // can be changed to change other properties, not DACL, relying on SECURITY_DESCRIPTOR_CONTROL parameters https://msdn.microsoft.com/ru-ru/library/windows/desktop/aa379566%28v=vs.85%29.aspx
        IntPtr sd_ptr = new IntPtr();
        UIntPtr sd_size_ptr = new UIntPtr();
        ConvertStringSecurityDescriptorToSecurityDescriptor(sddl, sd_revision, out sd_ptr, out sd_size_ptr);
        SetFileSecurity(path, DACL_SECURITY_INFORMATION, sd_ptr);
    }
}

此代码从Advapi32.dll到C#代码的导入功能。 特别感谢PInvoke.net! 将此代码添加到代码示例中。

答案 1 :(得分:-1)

您可以使用powershell命令获取文件或文件夹(符号链接/连接)的sddl:get-acl -path“ c:\ some \ file_or_folder” |

将输出插入到fl会将acl转换为详细列表和ssdl形式。

对于文件夹“ C:\ Users \ someuser \ Application Data”,sddl是

p:O:SYG:SYD:AI(D ;; CC ;;; WD)(A; OICIID; FA ;;; SY)(A; OICIID; FA ;;; BA)(A; OICIID; FA ;; ; S-1-5-21-2614944367-2017529714-1376493066-1XXX)

O:SY所有者:NT Authority / System G:SY集团:NT Authority /系统 D:AI(D ;; CC ;;; WD)(A; OICIID; FA ;;; SY)(A; OICIID; FA ;;; BA)(A; OICIID; FA ;;; S-1-5- 21-2614944367-2017529714-1376493066-1XXX)

“ D:”表示DACL “ AI”的含义类似于“允许继承”

括号中的每个子字符串是一个访问控制项(ACE)。每个ACE包含六个用分号分隔的字段,这些字段指示实际的权限。第一个ACE(D ;; CC ;;; WD)对应于详细的列表行:Everyone Deny ReadData。也就是说,D表示拒绝,CC表示ReadData,而WD表示所有人。请注意,Microsoft文档中显示的CC代码与Sddl.h中的SDDL_CREATE_CHILD和访问权限值ADS_RIGHT_DS_CREATE_CHILD同义。 CC如何解释为“ ReadData”还不清楚。还要注意,指定“每个人”都是使用代码WD(可能是从“世界”派生的)完成的,而不是使用SID。

对于那些希望深入研究的人,请参见https://docs.microsoft.com/en-us/windows/win32/secauthz/security-descriptor-string-format

https://docs.microsoft.com/en-us/windows/win32/secauthz/security-descriptor-definition-language-for-conditional-aces-

https://docs.microsoft.com/en-us/windows/win32/secauthz/ace-strings

祝你好运!