C#中DirectoryEntry读取域审计规则返回空集合问题求助
解决C#读取域审计权限返回空集合的问题
问题核心
使用PowerShell的Get-Acl -Audit能正常获取域的审计规则,但C#通过DirectoryEntry.ObjectSecurity.GetAuditRules返回空集合,访问规则却可以正常读取。需要程序化管理100+独立域的审计权限。
关键原因
域的审计规则存储在**系统访问控制列表(SACL)中,而访问规则在自主访问控制列表(DACL)**中。默认情况下:
DirectoryEntry.ObjectSecurity仅加载DACL,不会主动获取SACL;- 读取SACL需要特殊权限(需拥有“管理审核和安全日志”权限);
- 你之前尝试的ActiveDs代码错误读取了DACL(
sd.DiscretionaryAcl),而非存储审计规则的SACL(sd.SystemAcl)。
解决方案
方案1:使用ActiveDs读取SACL
修正你的ActiveDs代码,直接读取存储审计规则的SystemAcl:
using ActiveDs; string path = "LDAP://demo.local/DC=demo,DC=local"; DirectoryEntry domain = new DirectoryEntry(path); // 确保获取到ntSecurityDescriptor属性 if (domain.Properties["ntSecurityDescriptor"].Count == 0) domain.RefreshCache(new[] { "ntSecurityDescriptor" }); var sd = (IADsSecurityDescriptor)domain.Properties["ntSecurityDescriptor"][0]; // 读取SACL(系统访问控制列表,存储审计规则) var sacl = (IADsAccessControlList)sd.SystemAcl; foreach (IADsAccessControlEntry ace in sacl) { // 筛选审计类型的ACE if ((ace.AceType & ADS_ACETYPE_ENUM.ADS_ACETYPE_SYSTEM_AUDIT_OBJECT) == ADS_ACETYPE_ENUM.ADS_ACETYPE_SYSTEM_AUDIT_OBJECT) { Console.WriteLine($"受信者: {ace.Trustee}"); Console.WriteLine($"访问掩码: {ace.AccessMask:X8}"); Console.WriteLine($"审计标志: {ace.AceFlags}"); } }
方案2:使用System.DirectoryServices.Protocols(推荐)
通过LdapConnection显式请求包含SACL的安全描述符,更灵活且可控:
using System.DirectoryServices.Protocols; using System.Security.AccessControl; using System.Security.Principal; var ldapConn = new LdapConnection("demo.local"); // 若需要指定凭据,可使用: // ldapConn.Credential = new NetworkCredential("username", "password", "demo.local"); ldapConn.Bind(); var searchReq = new SearchRequest( "DC=demo,DC=local", "(objectClass=domain)", SearchScope.Base, "ntSecurityDescriptor" ); // 添加控制,明确请求返回包含SACL的安全描述符 var sdControl = new SecurityDescriptorControl( SecurityDescriptorFlag.SeSaclPresent | SecurityDescriptorFlag.SeSaclEnabled ); searchReq.Controls.Add(sdControl); var searchResp = (SearchResponse)ldapConn.SendRequest(searchReq); var sdBytes = (byte[])searchResp.Entries[0].Attributes["ntSecurityDescriptor"][0]; // 解析安全描述符并获取审计规则 var sd = new CommonSecurityDescriptor(true, true, sdBytes, 0); var auditRules = sd.GetAuditRules(true, true, typeof(NTAccount)); Console.WriteLine($"审计规则总数: {auditRules.Count}"); foreach (AuditRule rule in auditRules) { Console.WriteLine($"{rule.IdentityReference} | 审计类型: {rule.AuditFlags}"); }
必要权限配置
确保运行程序的账号具备:
- 域管理员或等效权限;
- 在域控制器的本地组策略或域组策略中,配置“计算机配置→Windows设置→安全设置→本地策略→用户权限分配→管理审核和安全日志”权限,将账号添加进去。
内容的提问来源于stack exchange,提问作者Rampiid
相关产品推荐
相关产品推荐

