技术问询:检查文件ACL中Everyone组权限及获取其SID与安全描述符
检查文件ACL中Everyone组权限的实现方案
我最近刚好在折腾类似的需求——要确认文件的ACL里是否明确包含Everyone用户组,还要搞清楚这个组有没有比如写入这类实际可操作的访问权限,分享下我整理的实现步骤:
1. 先拿到Everyone组的SID
Everyone组的SID是系统固定的,我们可以直接通过AllocateAndInitializeSid生成,不用去查用户组列表:
SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; DWORD dwRes = AllocateAndInitializeSid( &SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pSIDEveryone );
⚠️ 注意: 用完pSIDEveryone一定要调用FreeSid(pSIDEveryone)释放内存,别留内存泄漏的坑。
2. 获取文件的安全描述符和ACL
接下来用GetNamedSecurityInfo获取目标文件的安全信息,我们重点要拿DACL(自由访问控制列表),因为所有用户/组的权限规则都存在这里:
DWORD dwRes = GetNamedSecurityInfo( lpszOwnFile, // 目标文件路径 SE_FILE_OBJECT, // 对象类型是文件 DACL_SECURITY_INFORMATION, // 指定要获取DACL信息 NULL, NULL, // 不需要所有者、组信息,传NULL &pDacl, // 输出获取到的DACL NULL, // 不需要SACL &pSecurityDescriptor // 输出安全描述符,后续要释放 );
⚠️ 注意: 调用成功后,pDacl就是我们要遍历的ACL对象,用完后记得用LocalFree(pSecurityDescriptor)释放安全描述符。
3. 遍历ACL检查Everyone的权限
拿到DACL后,我们需要逐个遍历里面的ACE(访问控制项),做两步判断:
- 这个ACE对应的SID是不是Everyone组的
- 这个ACE是允许还是拒绝权限,以及具体有哪些权限(比如写入)
核心逻辑代码大概是这样:
if (pDacl != NULL) { for (DWORD i = 0; i < pDacl->AceCount; i++) { LPVOID pAce = NULL; if (GetAce(pDacl, i, &pAce)) { // 区分允许和拒绝类型的ACE if (pAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE || pAce->Header.AceType == ACCESS_DENIED_ACE_TYPE) { PACCESS_ALLOWED_ACE pAllowedAce = (PACCESS_ALLOWED_ACE)pAce; // 对比SID是否匹配Everyone组 if (EqualSid(pAllowedAce->SidStart, pSIDEveryone)) { // 检查是否有写入相关权限 if (pAllowedAce->Mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) { if (pAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) { // 这里就是Everyone组被允许写入的情况 } else { // 这里是Everyone组被拒绝写入的情况(拒绝权限优先级更高) } } } } } } }
几个要注意的细节
- 调用这些API需要足够的权限,比如至少要有文件的
READ_CONTROL权限才能读取安全信息 - 一定要处理API返回的错误码,比如
AllocateAndInitializeSid可能因为内存不足失败,GetNamedSecurityInfo也可能返回权限不足的错误 - 所有通过API分配的内存都要记得释放,避免内存泄漏
内容的提问来源于stack exchange,提问作者elklepo
相关产品推荐
相关产品推荐

