【windows 访问控制】十一、C# 实操 对象 System.Security.AccessControl 命名空间

 AccessControl 命名空间 结构图

 

 

 解说:

DirectorySecurity=目录ACL
FileSecurity=文件ACL
FileSystemAuditRule=目录和文件中SACL中的ACE
FileSystemAccessRule=目录和文件中DACL中的ACE
GetAccessControl=ACL(AccessControlList)The security descriptors of all the access control sections of the directory.

DirectorySecurity类和FileSecurity类是对基础Microsoft Windows文件安全系统的抽象。----注:本文部分内容改编自《.NET安全揭秘》

FileSystemAccessRuleFileSystemAuditRule 类是对组成DACLSACL的访问控制项(ACE)的抽象----注:本文部分内容改编自《.NET安全揭秘》 

 

 

 

 案例1、window平台的ACL、 ACE操作实例

 

 給文件夹添加访问控制项(ACE:), 要以管理员的方式运行vs2022,这样才能正确的添加sACE,特权。

新建一个ACL

第一方式,新建一个ACL,然后赋值给文件,这种方式会覆盖原来ACL的列表。并且对文件的sACE,dACE经行增删改

using System.Diagnostics;
using System.Security.AccessControl;
using System.Security.Principal;

//把桌面设置未当前目录
 Directory.SetCurrentDirectory(Environment.GetFolderPath(Environment.SpecialFolder.Desktop  ));
//用n


#region 添加ACE

//新建ACE ,ACE 

FileSystemAuditRule SACE = new("TestAccount", FileSystemRights.FullControl, AuditFlags.Success);
FileSystemAuditRule SACE2 = new(WindowsIdentity.GetCurrent().Name, FileSystemRights.Read, AuditFlags.Failure);
FileSystemAuditRule SACE3 = new("TestAccount", FileSystemRights.Modify, AuditFlags.Failure);


FileSystemAccessRule DACE = new("TestAccount" ,FileSystemRights.FullControl,AccessControlType.Deny);
FileSystemAccessRule DACE2 = new(WindowsIdentity.GetCurrent().Name, FileSystemRights.Read|FileSystemRights.Write,InheritanceFlags.None,PropagationFlags.None, AccessControlType.Allow);
FileSystemAccessRule DACE3 = new("TestAccount", FileSystemRights.Read , AccessControlType.Allow);


//关联桌面的已经存在的CSD文件夹
DirectoryInfo dir = new  ("CSD");

//获取文件的ACL
DirectorySecurity ACL=dir.GetAccessControl();

//将sACEs、dACLs加入ACL
ACL.AddAccessRule(DACE);
ACL.AddAccessRule(DACE2);
ACL.AddAccessRule(DACE3);

ACL.AddAuditRule(SACE);
ACL.AddAuditRule(SACE2);
ACL.AddAuditRule(SACE3);

dir.SetAccessControl(ACL);

//获取文件夹SACL权限
DirectorySecurity AClwithAudit = dir.GetAccessControl(AccessControlSections.Audit);

foreach (FileSystemAuditRule item in AClwithAudit.GetAuditRules(true, true, typeof(NTAccount)))
{
    Console.WriteLine(item.AuditFlags);

}
Console.Read();

//获取文件夹DACL权限
DirectorySecurity AClwithAccess = dir.GetAccessControl(AccessControlSections.Access);

foreach (FileSystemAccessRule item in AClwithAccess.GetAccessRules(true, true, typeof(NTAccount)))
{
    Console.WriteLine(item.AccessControlType );
}
#endregion 

//removeDACE("TestAccount","CSD",AccessControlType.Deny);
RemoveAllDACE("TestAccount","CSD");
/// <summary> /// 删除指定用户的文件夹dACE /// </summary> static void RemovedDACE(string username,string fielname, AccessControlType Type) { DirectoryInfo dir = new (fielname); DirectorySecurity AClwithAccess = dir.GetAccessControl(AccessControlSections.Access); foreach (FileSystemAccessRule dace in AClwithAccess.GetAccessRules(true, true, typeof(NTAccount))) { Console.WriteLine(dace.IdentityReference.Value); if (dace.AccessControlType == Type && dace.IdentityReference.Value == @$"{Environment.UserDomainName}\{username}") { AClwithAccess.ModifyAccessRule(AccessControlModification.Remove, dace, out bool ivalue); if (ivalue == true) { dir.SetAccessControl(AClwithAccess); Console.WriteLine("移除成功"); } } } } /// <summary> /// 删除指定用户在指定文件夹的所有D-ACE权限 /// </summary> static void RemoveAllDACE(string username,string filename) { DirectoryInfo dir = new (filename); DirectorySecurity AClwithAccess = dir.GetAccessControl(); AClwithAccess.PurgeAccessRules(new NTAccount(@$"{Environment.UserDomainName}\{username}")); dir.SetAccessControl(AClwithAccess); Console.WriteLine("移除成功"); } /// <summary> /// 删除指定用户的文件夹sACE /// </summary> static void RemovedSACE(string username, string fielname, AuditFlags Type) { DirectoryInfo dir = new(fielname); DirectorySecurity AClwithAccess = dir.GetAccessControl(AccessControlSections.Access); foreach (FileSystemAuditRule sace in AClwithAccess.GetAuditRules(true, true, typeof(NTAccount))) { Console.WriteLine(sace.IdentityReference.Value); if (sace.AuditFlags == Type && sace.IdentityReference.Value == @$"{Environment.UserDomainName}\{username}") { AClwithAccess.ModifyAuditRule(AccessControlModification.Remove, sace, out bool ivalue); if (ivalue == true) { dir.SetAccessControl(AClwithAccess); Console.WriteLine("移除成功"); } } } } /// <summary> /// 删除指定用户在指定文件夹的所有S-ACE权限 /// </summary> static void RemovedALLSACE(string username, string filename) { DirectoryInfo dir = new(filename); DirectorySecurity AClwithAudit = dir.GetAccessControl(); AClwithAudit.PurgeAuditRules(new NTAccount(@$"{Environment.UserDomainName}\{username}")); dir.SetAccessControl(AClwithAudit); Console.WriteLine("移除成功"); }

 

下面详细的介绍一下比较重要的几个方法,第一个:

一、 public FileSystemAccessRule( string identity, FileSystemRights fileSystemRights, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AccessControlType type)

定义访问规则,参数如下:

复制代码
identity   
  Type:     System.String
  The name of a user account. (账户名)
fileSystemRights
   Type:     System.Security.AccessControl.FileSystemRights
  One of the FileSystemRights values that specifies the type of operation associated with the access rule. (与访问规则相关联的操作类型)
inheritanceFlags
    Type:     System.Security.AccessControl.InheritanceFlags
  One of the InheritanceFlags values that specifies how access masks are propagated to child objects.
  (CSDN上解释的是“该值指示如何将访问掩码传播到子对象”,我的理解是 该值规定是将继承规则作用在文件夹上还是文件上)
propagationFlags
    Type:     System.Security.AccessControl.PropagationFlags
  One of the PropagationFlags values that specifies how Access Control Entries (ACEs) are propagated to child objects.
  (CSDN上解释的是“该值指定如何将访问控制项 (Ace) 传播到子对象”,propagationFlags能起作用的前提是inheritanceFlags不为None)
type
    Type:     System.Security.AccessControl.AccessControlType
  One of the AccessControlType values that specifies whether to allow or deny the operation.(允许还是拒绝)
复制代码

第一个参数是账户名,第二个是操作类型,操作类型对应的有以下:

复制代码
("AppendData", "附加数据");
("ChangePermissions", "更改权限");
("CreateDirectories", "创建文件夹/附加数据");
("CreateFiles", "创建文件/写入数据");
("Delete", "删除");
("DeleteSubdirectoriesAndFiles", "删除子文件夹及文件");
("ExecuteFile", "执行文件");
("FullControl", "完全控制");
("ListDirectory", "列出文件夹/读取数据");
("Modify", "修改");
("Read", "读取");
("ReadAndExecute", "读取和执行");
("ReadAttributes", "读取属性");
("ReadData", "读取数据");
("ReadExtendedAttributes", "读取扩展属性");
("ReadPermissions", "读取权限");
("Synchronize", "同步");
("TakeOwnership", "更改文件(夹)所有者");
("Traverse", "执行程序");
("Write", "写入");
("WriteAttributes", "写入属性");
("WriteData", "写入数据");
("WriteExtendedAttributes", "写入扩展属性");
复制代码

第三四个参数比较难懂,并且他两个应该组合起来应用。一个是inheritanceFlags(ContainerInherit,None,ObjectInherit),另一个是propagationFlags(InheritOnly,None,NoPropagateInherit),这两枚举都有三个值,都具有允许其成员值的按位组合的 FlagsAttribute 特性,propagationFlags能起作用的前提是inheritanceFlags不为None。

下面是我总结的常用的枚举组合:

 

 

 

对应到windows界面操作上后,如下图所示:

 

 

第五个参数规定该访问规则的类型是 允许还是拒绝。

 

 现有的ACL上添加ACE

using System.Security.AccessControl;
using System.Security.Principal;
//把桌面设置未当前目录
 Directory.SetCurrentDirectory(Environment.GetFolderPath(Environment.SpecialFolder.Desktop  ));

//新建ACE ,ACE的拥有者设置成当前 操作系统用
FileSystemAuditRule SACE=new FileSystemAuditRule(WindowsIdentity.GetCurrent().Name,FileSystemRights.FullControl,AuditFlags.Success);
FileSystemAccessRule DACE = new FileSystemAccessRule(WindowsIdentity.GetCurrent().Name,FileSystemRights.FullControl,AccessControlType.Deny);
FileSystemAccessRule DACE2 = new FileSystemAccessRule(WindowsIdentity.GetCurrent().Name, FileSystemRights.Read|FileSystemRights.Write,InheritanceFlags.None,PropagationFlags.None, AccessControlType.Allow);

 

//新建文件,并且ACL把文件添加到目录上。会和原来的ACL列表合并
DirectoryInfo dir = new DirectoryInfo("CSD");
DirectorySecurity sd=dir.GetAccessControl();
sd.AddAccessRule(DACE);
sd.AddAccessRule(DACE2);

dir.SetAccessControl(sd);

 遍历ACL中的ACE

遍历ACL中的ACE

            AuthorizationRuleCollection rules = fileAcl.GetAccessRules(true, true, typeof(NTAccount));
            // AuthorizationRule Rule = rules[0];
            foreach (FileSystemAccessRule rule in rules)
            {
                if(rule.IdentityReference.Value.CompareTo("Users")==0)
               {
                fileAcl.RemoveAccessRule(rule);
               }
            }

文件夹权限继承控制

DirectorySecurity ss = di.GetAccessControl();

ss.SetAccessRuleProtection(true,true);//这个是保护acl,防止继承,true为启用保护,这样就不会继承父类了,第二项是否保留已经继承的。

 

 获取ACE的掩码

using System.Security.AccessControl;
using System.IO;
using System.Security.Principal;
using System.Reflection;
 
Directory.SetCurrentDirectory(Environment.GetFolderPath(Environment.SpecialFolder.Desktop));    
DirectoryInfo di = new("CSD");

DirectorySecurity ss = di.GetAccessControl();

Console.WriteLine(ss.GetGroup(typeof(NTAccount)));
foreach (FileSystemAccessRule ace in ss.GetAccessRules(true,true,typeof(NTAccount)))
{
    Type getMask = typeof(FileSystemAccessRule);
    PropertyInfo propertyInfo = getMask.GetProperty("AccessMask", BindingFlags.Instance|BindingFlags.NonPublic | BindingFlags.GetProperty);
 int Mask  =int.Parse( propertyInfo.GetValue(ace, null).ToString());
   



 Console.WriteLine($"AccessControltype:{ace.FileSystemRights}  AcessMask:{ Convert.ToString(Mask, 2).PadLeft(32,'0') }");   

    
}

 

 

 

 案例2、通用平台的ACL ACE操作实例

 

这些方式是操作SD类型的通用方式(与底层的Windows资源的类型无关),.NET提供了如下类型:

 

1. 表示SD
  • System.Security.AccessControl.GenericSecurityDescriptor
  • System.Security.AccessControl.CommonSecurityDescriptor
  • System.Security.AccessControl.RawSecurityDescriptor
2. 表示ACLDACLSACL
  • System.Security.AccessControl.GenericAcl
  • System.Security.AccessControl.CommonAcl
  • System.Security.AccessControl.DescretionaryAcl
  • System.Security.AccessControl.SystemAcl
  • System.Security.AccessControl.RawAcl
3. 表示一个ACE
  • System.Security.AccessControl.GenericAce
  • System.Security.AccessControl.CustomAce
  • System.Security.AccessControl.KnownAce
  • System.Security.AccessControl.CompoundAce
  • System.Security.AccessControl.QualifiedAce
  • System.Security.AccessControl.CommonAce
  • System.Security.AccessControl.ObjectAce

 

示例:创建一个SD,向其DACL中添加ACE并将其转化为一个代表Windows资源的特殊SD(此处为互斥体)。

 

using System; 
using System.Security.AccessControl; 
using System.Security.Principal; 
class Program { 
static void Main() { 
//创建一个新的SD 
CommonSecurityDescriptor csd = new CommonSecurityDescriptor(false, false, string.Empty); 
DiscretionaryAcl dacl = csd.DiscretionaryAcl; 
//向DACL中添加ACE 
dacl.AddAccess( 
AccessControlType.Allow, // 枚举Allow、Deny. 
WindowsIdentity.GetCurrent().Owner, 
(int)MutexRights.TakeOwnership | (int)MutexRights.Synchronize, 
InheritanceFlags.None, // 禁用ACE继承
PropagationFlags.None); 
  
string sSDDL = csd.GetSddlForm( AccessControlSections.Owner ); 
  
MutexSecurity mutexSec = new MutexSecurity(); 
mutexSec.SetSecurityDescriptorSddlForm( sSDDL ); 
AuthorizationRuleCollection aces = mutexSec.GetAccessRules(true, true, typeof(NTAccount)); 
foreach ( AuthorizationRule ace in aces ) { 
if (ace is MutexAccessRule) { 
MutexAccessRule mutexAce = (MutexAccessRule)ace; 
Console.WriteLine( "-->SID : " + mutexAce.IdentityReference.Value ); 
Console.WriteLine( "访问权限类型:" + mutexAce.AccessControlType.ToString()); 
if (0xffffffff == (uint) mutexAce.MutexRights) 
Console.WriteLine( "拥有所有权限" ); 
else
Console.WriteLine( "权限: " + mutexAce.MutexRights.ToString()); 
} 
} 
} 
}

 

posted @ 2021-12-03 16:35  小林野夫  阅读(946)  评论(0编辑  收藏  举报
原文链接:https://www.cnblogs.com/cdaniu/