9个版本 (4个重大更新)
0.5.1 | 2024年4月16日 |
---|---|
0.5.0 | 2024年4月4日 |
0.4.0 | 2023年11月9日 |
0.3.0 | 2023年10月21日 |
0.1.2 | 2022年3月2日 |
#89 in Unix API
529 monthly downloads
用于 zuk
105KB
1.5K SLoC
extrasafe
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过滤器、syscall过滤功能,以防止您的程序调用不需要的syscalls,Landlock Linux安全模块以对IO操作进行更细粒度的控制,以及用户命名空间以实现更广泛的隔离。这些工具被systemd、Chrome、容器运行时和应用沙箱(如bubblewrap和firejail)使用。
extrasafe的目标是使您能够轻松地为您的程序添加额外的安全功能,而无需依赖运行软件的人进行外部配置。
seccomp非常简单,因此我们提供了简单的默认设置,使误用变得困难:默认拒绝,并预先选择了一组syscalls以启用。
此外,我们还支持一些稍微高级的使用案例
- 仅允许读取/写入stdin/out/err
- 允许读取/写入特定文件(在加载seccomp过滤器之前打开的文件)
- 您可以通过实现RuleSet trait来定义自己的允许的syscalls集合。
我们还支持使用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的Isolate
使用用户命名空间以及关于extrasafe其余功能的更详细信息,请参阅此处用户指南并查看示例目录
extrasafe是为谁准备的?
应用程序开发者,他们想要严格控制他们的程序可以做什么和不能做什么。
如果您正在开发库,您有三件事情可以做
- 提供覆盖您的库功能的
extrasafe::RuleSet
- 提供一种预先执行IO相关工作的
init
函数(例如:读取配置文件、SSL证书)。 - 如果你的库有任何独立的工作线程,你可以在工作线程中使用extrasafe。
你不想直接在库中使用extrasafe,因为你不知道你的依赖项将使用哪些功能。
目前extrasafe仅支持x86_64
架构。如果你想支持其他架构,请提交一个问题。
其他用途
你可能能够使用extrasafe来帮助测试某些边缘情况,比如网络不可用或无法读取文件,但我想这个用例可能更适合由单独的库来处理。如果你感兴趣,请给我发邮件!
为什么?
这样你可以更加安全。假设你的程序有一个存在未知RCE的依赖项:extrasafe允许你通过禁用不需要的功能和文件来部分降低风险。
可以避免利用的特定漏洞示例(寻找贡献者!)
- https://seclists.org/oss-sec/2022/q1/55
- 在不具有特权的模式下,依赖于能够调用
unshare
。
- 在不具有特权的模式下,依赖于能够调用
- log4j RCEs
- 依赖于能够进行网络调用,所以extrasafe可以通过以下方式减轻这种影响:
- 如果你的程序不需要网络访问,不要给它访问权限(但通常情况下,你实际上也不太可能被利用)
- 在具有网络访问权限的单独线程中进行日志记录
- 依赖于能够进行网络调用,所以extrasafe可以通过以下方式减轻这种影响:
- 涉及执行SUID-root二进制文件的漏洞依赖于能够fork和exec。
- https://nickgregory.me/linux/security/2022/03/12/cve-2022-25636/
- nftables依赖于能够创建类型为
AF_NETLINK
的套接字,这可以通过seccomp进行过滤
- nftables依赖于能够创建类型为
- https://googleprojectzero.blogspot.com/2022/03/racing-against-clock-hitting-tiny.html
- 这里涉及许多事情,但dup和timerfd都没有在启用extrasafe时默认启用
- https://lwn.net/ml/oss-security/[email protected]/
- nftables再次,extrasafe默认禁用了
AF_NETLINK
套接字。
- nftables再次,extrasafe默认禁用了
注意事项
Seccomp过滤器是一种相当粗糙的工具。
- 它们不允许你在
open
调用中根据路径名进行过滤,或者实际上任何指向指针的syscall参数(但我们现在支持Landlock!) - 它们的最小作用域单位是线程,所以如果你想保护可能具有风险解析代码的热点内循环,你可能需要想出一种快速在现有线程之间传递数据的方法,而不是每次都启动一个新的线程。
为什么不使用X?
为什么不两者都使用?继续阅读。
为什么不使用systemd的内置seccomp支持?
systemd通过SystemCallFilter
属性支持使用seccomp过滤子进程的syscall。参见这篇文章和systemd文档
问题
- Systemd特定的
- 排除了为例如BSD编写后端使用
pledge
的情况 - 不如细粒度
- extrasafe允许你打开文件然后关闭进一步的访问,例如。
- extrasafe允许你使用seccomp syscall参数过滤功能,例如,只接受在预先分配的套接字文件描述符上的连接。
- 通过将安全配置文件放入代码中,它可以从维护代码库的所有工作中受益:源代码控制、自动化测试、代码覆盖率,因此你可以确保在代码部署的任何时间和地点,你的安全配置文件都符合指定。
对于那些正在阅读此文档并说“但是我不想相信开发者正确编写了他们的seccomp过滤器!”的系统管理员或DevOps人员——太好了!深度防御是我们的目标,你可以并且应该继续使用AppArmor或你偏好的外部安全控制系统。
那么AppArmor或SELinux呢?
如上所述,你应该继续使用AppArmor和SELinux等Linux安全模块!并不是每个程序都会使用extrasafe。
同样,从一个开发者的角度来看,也没有保证运行你代码的人在使用它们。当你的开源代码在成千上万的机器上运行(这些机器不在你的控制之下)并存在bug时,知道它不容易被利用并且可以在你的空闲时间修复,而不是需要协调大规模的补丁和升级工作来确保系统的安全,这要舒服得多。
开发
测试
make测试
代码检查 / clippy
make代码检查
代码覆盖率
make覆盖率
依赖关系
~1MB
~16K SLoC