如何在 C# 中编辑 DACL?
How can I edit a DACL in C#?
是否有 SetFileSecurity
function 的类似物?
我需要重写 Python 中的一些测试,我被卡在了这一部分。在 Python 中,我可以使用 pywin32
自由编辑 DACL(具有 C++ 实现的模块可与 Windows API 一起使用)。
我可以使用 win32security
.
编辑任何 ACE
将所有者更改为 Everyone
?好的。
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 更改安全描述符,但是如果在没有 SeSecurityPrivilege
权限的情况下调用 SetSecurityDescriptorSddlForm
,则将 System.Security.File.SetAccessControl()
与 FileSecurity
一起使用将不起作用。此外,即使使用具有几乎所有权限的管理员令牌,如果我想以 "wrong" 方式更改某些内容(删除一些继承的 ACE),安全描述符也不适用。如果我尝试做一些事情 "very wrong",比如将所有者设置为 Everyone
,则会抛出异常。
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);
运行 管理员令牌:
Unhandled Exception: System.InvalidOperationException: The security identifier is not
allowed to be the owner of this object.
at System.Security.AccessControl.NativeObjectSecurity.Persist(String name, SafeHandle
handle,
AccessControlSections includeSections, Object exceptionContext)
at System.Security.AccessControl.NativeObjectSecurity.Persist(String name,
AccessControlSections includeSections, Object exceptionContext)
at System.Security.AccessControl.NativeObjectSecurity.Persist(String name,
AccessControlSections includeSections)
at System.Security.AccessControl.FileSystemSecurity.Persist(String fullPath)
at System.IO.File.SetAccessControl(String path, FileSecurity fileSecurity)
at rtest.Program.Main(String[] args) in C:\somepath\Program.cs:line 52
经过 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!
将此代码添加到代码示例中。
您可以使用 powershell 命令获取文件或文件夹 (symlink/junction) 的 sddl:get-acl -path "c:\some\file_or_folder" |佛罗里达
将输出通过管道传输到 fl 会将 acl 转换为详细列表和 ssdl 形式。
文件夹 "C:\Users\someuser\Application Data" 的 sddl 是
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 Owner:NT Authority/System
G:SY Group:NT Authority/System
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表示Deny,CC表示ReadData,WD表示Everyone。请注意,Microsoft 文档中显示的 CC 代码与 Sddl.h 中的 SDDL_CREATE_CHILD 和访问权限值 ADS_RIGHT_DS_CREATE_CHILD 同义。 CC 如何被解释为 "ReadData" 尚不清楚。另请注意,指定 "Everyone" 是使用代码 WD(可能派生自 "World")完成的,而不是使用 SID。
对于那些希望深入研究的人,请参阅 https://docs.microsoft.com/en-us/windows/win32/secauthz/security-descriptor-string-format
https://docs.microsoft.com/en-us/windows/win32/secauthz/ace-strings
祝你好运!
是否有 SetFileSecurity
function 的类似物?
我需要重写 Python 中的一些测试,我被卡在了这一部分。在 Python 中,我可以使用 pywin32
自由编辑 DACL(具有 C++ 实现的模块可与 Windows API 一起使用)。
我可以使用 win32security
.
将所有者更改为 Everyone
?好的。
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 更改安全描述符,但是如果在没有 SeSecurityPrivilege
权限的情况下调用 SetSecurityDescriptorSddlForm
,则将 System.Security.File.SetAccessControl()
与 FileSecurity
一起使用将不起作用。此外,即使使用具有几乎所有权限的管理员令牌,如果我想以 "wrong" 方式更改某些内容(删除一些继承的 ACE),安全描述符也不适用。如果我尝试做一些事情 "very wrong",比如将所有者设置为 Everyone
,则会抛出异常。
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);
运行 管理员令牌:
Unhandled Exception: System.InvalidOperationException: The security identifier is not
allowed to be the owner of this object.
at System.Security.AccessControl.NativeObjectSecurity.Persist(String name, SafeHandle
handle,
AccessControlSections includeSections, Object exceptionContext)
at System.Security.AccessControl.NativeObjectSecurity.Persist(String name,
AccessControlSections includeSections, Object exceptionContext)
at System.Security.AccessControl.NativeObjectSecurity.Persist(String name,
AccessControlSections includeSections)
at System.Security.AccessControl.FileSystemSecurity.Persist(String fullPath)
at System.IO.File.SetAccessControl(String path, FileSecurity fileSecurity)
at rtest.Program.Main(String[] args) in C:\somepath\Program.cs:line 52
经过 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! 将此代码添加到代码示例中。
您可以使用 powershell 命令获取文件或文件夹 (symlink/junction) 的 sddl:get-acl -path "c:\some\file_or_folder" |佛罗里达
将输出通过管道传输到 fl 会将 acl 转换为详细列表和 ssdl 形式。
文件夹 "C:\Users\someuser\Application Data" 的 sddl 是
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 Owner:NT Authority/System G:SY Group:NT Authority/System 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表示Deny,CC表示ReadData,WD表示Everyone。请注意,Microsoft 文档中显示的 CC 代码与 Sddl.h 中的 SDDL_CREATE_CHILD 和访问权限值 ADS_RIGHT_DS_CREATE_CHILD 同义。 CC 如何被解释为 "ReadData" 尚不清楚。另请注意,指定 "Everyone" 是使用代码 WD(可能派生自 "World")完成的,而不是使用 SID。
对于那些希望深入研究的人,请参阅 https://docs.microsoft.com/en-us/windows/win32/secauthz/security-descriptor-string-format
https://docs.microsoft.com/en-us/windows/win32/secauthz/ace-strings
祝你好运!