祝大家 2024 元旦快乐!🎉
如果你喜欢 Rust ,想要深入 Rust,那么欢迎加入 Rust 研学团。
这是一个独特的、付费的学习社区,专注于探索和理解开源项目中的 Rust 代码。在这里,你将有机会不仅学习 Rust 的基础知识,还能深入其核心概念和实际应用。我们的目标是通过实际的代码案例,让你在 Rust 编程领域迅速成长。你将有机会深入研究各种开源项目,分析它们的架构、设计模式和性能优化策略。
专栏用户可私信我加入 Rust 研学群。
““ sudo 命令算是一个典型的安全关键工具,它既普遍存在又不被重视。对于这类工具的安全改进将对整个行业产生巨大影响。” —— Chainguard (一家网络安全公司)的首席执行官兼联合创始人丹·洛伦克(Dan Lorenc)
有如下三点理由:
第一,我非常喜欢 Rust 语言。
第二,进入三十五岁之后,我对人生的意义思考了很多,除了为了赚钱生存,应该留下点活着的痕迹,证明我为此生绽放过生命。所以我一直坚持写作写代码,将我的生命化为文字、化为代码,是我绽放生命的方式。尤其是代码,我职业生涯的前十几年写了很多代码,但是大多无意义。我想要写真正有用的代码,所以我从应用开发一路转向了底层基础设施系统开发。因为底层系统的寿命相比应用更加持久。
第三,sudo 是被广泛使用的基础软件,代码量也不是很多。并且现在有一个用 Rust 重写它的机会,所以就想参与一下。
所以,sudo-rs 就是研学团的第一篇文章了。后续选择研学的开源项目也是这样挑选。
在深入 sudo-rs 之前,我们应该先了解 sudo 和 su 命令以及 Linux 系统的权限模型的相关背景知识。
Linux 操作系统采用一种基于权限的安全模型,其中每个文件和进程都有与之关联的权限,总的来说主要体现在下面两个方面:
1、文件权限 2、进程权限
文件权限包括五种:
“r:可读取文件内容或目录结构 w:可修改文件的内容或目录的结构(但不包括删除) x:文件可被系统执行或目录可被作为工作目录 s:文件在执行阶段具有文件所有者的权限 t:使一个目录既能够让任何用户写入文档,又不让用户删除这个目录下他人的文档
此外:
比如下面这行文件权限示例:
-rw-r--r-- 1 user user 4101 Dec 29 01:24 main.rs
它表示文件所有者具有读(r)和写(w)权限,文件所属组和其他用户只有读权限,没有写入或执行权限。
进程权限涉及两个权限 id:
每个Unix类操作系统中的用户都由一个不同的整数编号来识别,这个唯一的编号被称为用户ID。有三种类型的 UID 为一个进程定义,可以根据任务的特权动态更改。
real user id(ruid)
:真实用户 ID。对于一个进程来说,真实用户 ID 就是启动该进程的用户的用户 ID。它定义了该进程可以访问哪些文件。effective user id(euid)
:有效用户 ID。通常与真实用户 ID 相同,但有时会更改以使非特权用户能够访问只能由特权用户(如 root)访问的文件。saved user id(suid)
:当一个进程以提升的权限(通常是 root)运行时,需要执行一些非特权工作时,可以通过暂时切换到非特权账户来实现。在执行特权不足的工作时,有效的用户ID(UID)会被更改为较低的特权值,并将有效用户ID(EUID)保存为保存的用户ID(SUID),以便在任务完成后切换回特权账户。
如果您查看/usr/bin/passwd
文件的权限:
-rwsr-xr-x 1 root root 59640 Mar 23 2019 /usr/bin/passwd
所以,如果非 root 用户运行此文件,进程的有效用户ID将为“0”,即 root,而用户 ID 将保持与原始用户相同。一个进程是否能操作某个文件,取决于进程的euid
是否拥有这个文件的相应权限,而不是ruid
。在具体一点,如果想要让进程拥有 root 用户的权限,只需要将 euid
设置为 0
(root 的 id)。
所以,sudo 本质上是一个拥有者为 root 且拥有 s
权限的可执行文件。
su
是 "切换用户"(Switch User)的缩写。它允许当前用户切换到另一个用户,通常是超级用户(root)。su
命令,您可以切换到其他用户并使用该用户的权限来执行命令。sudo
是 "以超级用户权限执行"(Superuser Do)的缩写。它允许普通用户在不切换到超级用户的情况下以超级用户的权限来执行特定命令。sudo
命令提供了更加灵活和安全的权限管理方式,因为它允许管理员授予特定用户或用户组执行特定命令的权限,而无需分享超级用户密码。区别:
su
要求知道目标用户的密码,而 sudo
允许管理员授予特定命令的执行权限给用户,用户只需提供自己的密码。sudo
提供了更细粒度的权限控制,可以限制用户执行某些命令的能力。su
切换用户后,需要执行 exit
命令或注销才能返回原用户。普通用户需要通过输入自己的密码来验证身份,然后根据系统中的 sudoers
文件中的规则来决定是否允许执行特定命令。
sudoers
是一个配置文件,通常位于 /etc/sudoers
或 /etc/sudoers.d/
目录中,用于定义谁可以以超级用户的身份执行哪些命令。sudoers
文件包含一系列的规则,每个规则指定了一个用户或用户组以及他们被允许执行的命令。规则还可以包括有关密码验证、执行环境等的设置。sudoers
文件通常只能由超级用户(root)编辑,以确保安全性。sudo
也可以结合使用 PAM 可以增强系统的安全性和灵活性。PAM 可以提供以下功能:
sudo
命令之前必须通过密码验证。这可以防止未经授权的访问。sudo
命令时提供多种身份验证因素,如密码、智能卡、生物识别等。sudo
。sudo
活动,以便审计和跟踪用户操作。配置 sudo
与 PAM 结合使用通常涉及编辑 /etc/sudoers
文件,并添加适当的 PAM 模块。以下是一些配置示例:
// 配置 PAM 模块来要求用户提供多因素认证,例如密码和智能卡
auth required pam_unix.so
auth required pam_google_authenticator.so
// 使用 PAM 模块来检查账户状态,以确保只有合法用户可以使用 `sudo`
account required pam_unix.so
sudo-rs[1] 是 Prossimo 项目的一部分,由 ISRG 主导开发,并得到 NLNet 基金会的资助进行独立安全审核。开发团队是由 Ferrous Systems 和 Tweede Golf 团队组成的团队。
sudo 工具为类 Unix 系统(例如 Linux 和 FreeBSD)的特权用户提供了以 root 身份运行命令的方式。它存在一定的风险,因为低权限的恶意用户或软件可能会找到滥用它的方法,例如利用代码中的漏洞来提升他们的访问权限到 root 或超级用户级别。理想情况下,sudo 和 su 应该尽可能安全和无漏洞,因为它们作为控制系统的完全控制的入口。
根据 ISRG 的 Prossimo 项目执行主任 Josh Aas 的说法,原始 sudo 中三分之一的安全漏洞源于内存管理问题。
在 2023 年 8 月,`sudo-rs` 首次发布了 release 版本[2]。在用 Rust 重写 sudo-rs
时还带来了附加收益:sudo-rs
开发了一个测试套件,帮助发现了原始sudo
C 实现中的错误。因为 sudo
已经是一套非常成熟的软件了,用 Rust 对其重写,需要覆盖一份完整的功能测试套件。
在 2023 年 9月4日至9月15日,ROS(**Radically Open Security[3]**)对 sudo-rs 进行了水晶盒渗透测试,目的是验证在没有适当身份验证的情况下无法执行特权操作。此次审计是在 sudo-rs
代码库的 b5eb2c6
分支版本上于进行的,点此查看完整审计报告[4]。
ROS 团队发现了一个中等严重性问题和两个低严重性问题:
chown
调用的默认权限设置不正确(低)除了这些发现之外,ROS 还对 sudo-rs 代码库的不同组件进行了模糊测试,但没有发现任何问题。
sudo-rs
项目代码量虽然不是很多,但看上去实现逻辑比想象中的复杂,我是没想到实现 sudo 要这么多代码量。
sudo-rs
的 src
目录包含了多个子目录和文件,这些子目录和文件共同构成了项目的核心功能。以下是 src
目录的结构和内容概述:
sudo-rs
项目的一些通用功能相关的代码。su
命令功能的代码。sudo
命令功能的代码。sudoers
文件的代码。visudo
命令的实现,用于编辑 sudoers
文件。扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有