Rust操作Windows ACL的革命性工具:windows-acl库详解

本文深入介绍Trail of Bits开源的windows-acl Rust库,详解其如何简化Windows访问控制列表(ACL)编程,包含DACL/SACL操作原理、实际代码示例及在安全工具开发中的应用前景。

介绍 windows-acl:在 Rust 中操作 ACL - Trail of Bits 博客

访问控制列表(ACL)是 Microsoft Windows 安全模型的核心组成部分。除了控制对安全资源的访问外,它们还用于沙箱隔离、事件审计和指定强制完整性级别。然而以编程方式操作 ACL 异常困难,尤其是在 Rust 中。现在我们推出了解决方案——windows-acl,这是一个简化 Windows 访问控制列表操作的 Rust 库。

Windows ACL 简要背景

Windows 有两种类型的 ACL:自主访问控制列表(DACL)和系统访问控制列表(SACL)。Windows 中的每个安全对象(如文件、注册表项、事件等)都具有包含 DACL 和 SACL 的关联安全描述符。

DACL 和 SACL 的区别在于所包含条目的类型。DACL 用于控制实体对资源的访问权限。例如,要禁止用户读取注册表项,该注册表项的 DACL 需要包含相应用户的访问拒绝条目。SACL 用于管理生成审计事件所需的操作类型,并为资源设置强制完整性标签。例如,要审计用户组对特定文件的访问失败,该文件的 SACL 必须包含相应用户组的审计条目。

当前操作 ACL 的挑战

从现有 ACL 添加和删除条目需要创建新的 ACL。删除过程相对简单——复制除目标删除条目外的所有现有 ACL 条目。对于自主访问控制列表,插入过程更为复杂。DACL 允许用户访问的权限取决于 DACL 中 ACE 的排序顺序。开发人员需要负责在首选位置正确插入新的访问控制条目(ACE)。此外,新的 DACL 必须确保要插入的 ACE 与现有 ACE 条目没有冲突。例如,如果现有 DACL 包含具有读/写权限用户的访问允许条目,而要添加的 ACE 是仅具有读取权限用户的访问允许条目,则不得将现有条目复制到新 DACL 中。没有人愿意处理这种复杂性,尤其是在 Rust 中。

windows-acl 如何简化操作

让我们通过 appjaillauncher-rs 来演示 windows-acl 的简便性。去年,我将原始的 C++ AppJailLauncher 移植到 Rust。appjaillauncher-rs 使用 AppContainers 对 Windows 应用程序进行沙箱处理。为实现正确的沙箱功能,我需要修改特定资源的 ACL——在没有 Active Template Library 类(如 CDacl 和 CSacl)、.NET 框架或 PowerShell 帮助的情况下,这是一项艰巨的任务。我最终得到的解决方案既不完美又复杂。在实现 windows-acl 后,我回头更新了 appjaillauncher-rs 以使用 windows-acl。通过 windows-acl,我获得了处理 Windows ACL 编程难点的模块化库。它提供了简化添加和删除 DACL 及 SACL 条目操作的接口。

例如,添加 DACL 访问允许条目需要以下代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
match ACL::from_file_path(string_path, false) {
    Ok(mut acl) => {
        let sid = string_to_sid(string_sid).unwrap_or(Vec::new());
        if sid.capacity() == 0 {
            return false;
        }
        acl.remove(
            sid.as_ptr() as PSID, 
            Some(AceType::AccessAllow), None
        ).unwrap_or(0);
        if !acl.allow(sid.as_ptr() as PSID, true, mask).unwrap_or_else(|code| {
               false
           }) {
            return false;
        }
    },
    ...
}

同样地,删除 DACL 访问允许条目的代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
match ACL::from_file_path(string_path, false) {
    Ok(mut acl) => {
        let sid = string_to_sid(string_sid).unwrap_or(Vec::new());
        if sid.capacity() == 0 {
            return false;
        }
        let result = acl.remove(
                         sid.as_ptr() as PSID, 
                         Some(AceType::AccessAllow), 
                         None);
        if result.is_err() {
            return false;
        }
    },
    ...
}

windows-acl 的潜在应用与未来工作

windows-acl 库为使用 Rust 编写 Windows 安全工具开辟了新的可能性。操作 SACL 的能力使我们能够充分利用 Windows 事件审计引擎的强大功能。Windows 事件审计引擎在提供检测终端漏洞的信息方面发挥着关键作用。我们希望这项工作能为 Windows Rust 开发者社区做出贡献,并激励创建更多基于 Rust 的安全工具!

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计