#seccomp #syscalls #security #linux-kernel #linux #landlock

extrasafe-multiarch

通过减少可访问内容使代码更安全

2 个不稳定版本

0.4.0 2024年3月17日
0.1.6 2023年8月19日
0.1.5 2023年8月18日
0.1.4 2023年8月16日

Unix APIs 中排名第195

MIT 协议

87KB
1K SLoC

extrasafe

Coverage Status CI Status crates.io docs.rs

"信任无人,甚至你自己" - 互联网人

fn main() {
    println!("disabling syscalls...");

    extrasafe::SafetyContext::new()
        .enable(
           extrasafe::builtins::SystemIO::nothing()
              .allow_stdout()
              .allow_stderr()
   	    ).unwrap()
	.apply_to_all_threads().unwrap();

    // Opening files now fails!
    let res = File::create("should_fail.txt");
    assert!(res.is_err());

    println!("but printing to stdout still works!");
    eprintln!("and so does stderr!");
}

你已经使用了安全和不安全的Rust:现在你的代码可以是额外的安全。

extrasafe 是围绕 Linux 内核的 seccomp 系统调用过滤功能的一个包装器,以防止你的程序调用不需要的系统调用,支持 Landlock Linux 安全模块。Seccomp 本身不是一个完整的沙箱系统。

extrasafe 的目标是让用户轻松地为自己的程序添加额外安全,无需依赖运行软件的人员的外部配置。

seccomp 非常简单,因此我们提供了简单的默认设置,使其难以误用:默认拒绝,并预选了要启用的系统调用集。

此外,我们还支持一些稍微复杂的使用场景

  • 仅允许对 stdin/out/err 进行读写
  • 允许对特定文件进行读写(在加载 seccomp 过滤器之前打开的文件)
  • 您可以通过实现 RuleSet 特性来自定义允许的系统调用集。

我们还支持使用 Landlock 来允许对文件系统进行特定、针对性的访问

fn main() {
    let tmp_dir = tempfile::tempdir().unwrap().into_path();

    extrasafe::SafetyContext::new()
        .enable(
           extrasafe::builtins::SystemIO::nothing()
              .allow_create_in_dir(&tmp_dir)
              .allow_write_file(&tmp_dir)
        ).unwrap()
	.apply_to_current_thread().unwrap();

    // Opening arbitrary files now fails!
    assert!(File::open("/etc/passwd")
        .is_err());

    // But the directory we allowed works
    assert!(File::create(tmp_dir.join("my_output.txt"))
        .is_ok());

    // And other syscalls are still disallowed
    assert!(std::net::UdpSocket::bind("127.0.0.1:0")
        .is_err());
}

请查看用户指南

extrasafe 是为谁准备的?

应用程序 开发者,他们希望严格控制其程序可以做什么和不能做什么。

如果您正在开发库,您可以做三件事

  1. 提供覆盖库功能的 extrasafe::RuleSet
  2. 提供某种类型的 init 函数,在提前完成任何与 I/O 相关的工作(例如读取配置文件、SSL 证书)
  3. 如果您的库有任何类型的独立工作线程,您可以在工作线程中使用 extrasafe。

您不希望直接在库中使用 extrasafe,因为您不知道您的依赖项将使用哪些其他功能。

目前 extrasafe 仅支持 x86_64。如果您想帮助支持其他架构,请提交一个问题。

其他用途

您可以使用 extrasafe 来帮助测试某些边缘情况,例如网络不可用或无法读取文件,但我认为这种情况最好由单独的库来处理。如果您对此感兴趣,请给我发邮件!

为什么?

这样您可以更加安全。假设您的程序有一个未知RCE的依赖项隐藏在某个地方:extrasafe 允许您通过禁用对不需要的功能和文件的访问来部分规避这一点。

可以使用 seccomp 避免利用的漏洞的具体示例(寻求贡献!)

注意事项

Seccomp 过滤器是一种相对粗略的工具。

  • 它们不允许您在 open 调用中按路径名过滤,或者实际上任何是指针的 syscall 参数(但我们现在支持 Landlock!)
  • 它们的最小作用域单位是线程,因此如果您想保护可能在热内循环中风险较高的解析代码,您可能需要找到一种快速在现有线程之间传递数据的方法,而不是每次都启动一个新的线程。

为什么不使用 X?

为什么不两者都使用?继续阅读。

为什么不使用 systemd 内置的 seccomp 支持?

systemd 支持通过 SystemCallFilter 属性使用 seccomp 过滤子进程的 syscalls。参见这篇博客文章systemd 文档

问题

  • systemd 特定
  • 排除了为例如 BSD 编写后端使用 pledge
  • 不够精细
    • extrasafe 允许您打开文件然后关闭进一步的访问,例如。
    • extrasafe 允许您使用 seccomp syscall 参数过滤功能,例如仅接受在特定、预分配的套接字 fds 上的连接。
  • 将安全配置文件放在您的代码中,它可以从维护代码库的所有工作中受益:源代码控制、自动测试、代码覆盖率,因此您可以确保您的安全配置文件在代码部署的任何时间和地点都符合要求。

对于那些阅读此内容并说“但我不想相信开发人员正确编写了他们的 seccomp 过滤器”的系统管理员或 devops -太好了!深度防御是我们的目标,您可以使用并应该继续使用 AppArmor 或您选择的任何外部安全控制系统。

那么 AppArmor 或 SELinux 呢?

如上所述,您应该继续使用 Linux 安全模块如 AppArmor 和 SELinux!并非每个程序都会使用 extrasafe。

同样地,从开发者的角度来看,并不能保证运行你代码的人一定会使用它们。当你的开源代码在数千台你无法控制的机器上运行出现问题时,知道它不容易被利用并且可以在你方便的时候修复,比协调大规模的补丁和升级工作来确保系统安全要好得多。

开发

在将 just 打包到 Ubuntu/Debian 之前,你可以使用 make 作为简单的命令执行器,或者你可以直接运行 cargo 命令。

测试

maketest

代码检查 / clippy

makelint

代码覆盖率

makecoverage

依赖关系

~1MB
~16K SLoC