前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Rust 研学】 sudo-rs 源码分析 Part 1

【Rust 研学】 sudo-rs 源码分析 Part 1

作者头像
张汉东
发布2024-01-02 11:03:09
1880
发布2024-01-02 11:03:09
举报
文章被收录于专栏:Rust 编程Rust 编程

祝大家 2024 元旦快乐!🎉

Rust 研学团简介

如果你喜欢 Rust ,想要深入 Rust,那么欢迎加入 Rust 研学团

这是一个独特的、付费的学习社区,专注于探索和理解开源项目中的 Rust 代码。在这里,你将有机会不仅学习 Rust 的基础知识,还能深入其核心概念和实际应用。我们的目标是通过实际的代码案例,让你在 Rust 编程领域迅速成长。你将有机会深入研究各种开源项目,分析它们的架构、设计模式和性能优化策略。

专栏用户可私信我加入 Rust 研学群。

我为什么对 sudo-rs 感兴趣

““ sudo 命令算是一个典型的安全关键工具,它既普遍存在又不被重视。对于这类工具的安全改进将对整个行业产生巨大影响。” —— Chainguard (一家网络安全公司)的首席执行官兼联合创始人丹·洛伦克(Dan Lorenc)

有如下三点理由:

第一,我非常喜欢 Rust 语言。

第二,进入三十五岁之后,我对人生的意义思考了很多,除了为了赚钱生存,应该留下点活着的痕迹,证明我为此生绽放过生命。所以我一直坚持写作写代码,将我的生命化为文字、化为代码,是我绽放生命的方式。尤其是代码,我职业生涯的前十几年写了很多代码,但是大多无意义。我想要写真正有用的代码,所以我从应用开发一路转向了底层基础设施系统开发。因为底层系统的寿命相比应用更加持久。

第三,sudo 是被广泛使用的基础软件,代码量也不是很多。并且现在有一个用 Rust 重写它的机会,所以就想参与一下。

所以,sudo-rs 就是研学团的第一篇文章了。后续选择研学的开源项目也是这样挑选。

背景:sudo 与 su

在深入 sudo-rs 之前,我们应该先了解 sudo 和 su 命令以及 Linux 系统的权限模型的相关背景知识。

Linux 操作系统采用一种基于权限的安全模型,其中每个文件和进程都有与之关联的权限,总的来说主要体现在下面两个方面:

1、文件权限 2、进程权限

文件权限包括五种:

“r:可读取文件内容或目录结构 w:可修改文件的内容或目录的结构(但不包括删除) x:文件可被系统执行或目录可被作为工作目录 s:文件在执行阶段具有文件所有者的权限 t:使一个目录既能够让任何用户写入文档,又不让用户删除这个目录下他人的文档

此外:

  • 权限模型包括三种主要角色:所有者(Owner)、所属组(Group)和其他用户(Others)。
  • 权限模型通过数字表示权限,如 755 表示文件所有者具有读、写、执行权限,所属组和其他用户只有读和执行权限。

比如下面这行文件权限示例:

代码语言:javascript
复制
-rw-r--r-- 1 user user 4101 Dec 29 01:24 main.rs

它表示文件所有者具有读(r)和写(w)权限,文件所属组和其他用户只有读权限,没有写入或执行权限。

进程权限涉及两个权限 id:

每个Unix类操作系统中的用户都由一个不同的整数编号来识别,这个唯一的编号被称为用户ID。有三种类型的 UID 为一个进程定义,可以根据任务的特权动态更改。

  1. real user id(ruid):真实用户 ID。对于一个进程来说,真实用户 ID 就是启动该进程的用户的用户 ID。它定义了该进程可以访问哪些文件。
  2. effective user id(euid):有效用户 ID。通常与真实用户 ID 相同,但有时会更改以使非特权用户能够访问只能由特权用户(如 root)访问的文件。
  3. saved user id(suid):当一个进程以提升的权限(通常是 root)运行时,需要执行一些非特权工作时,可以通过暂时切换到非特权账户来实现。

在执行特权不足的工作时,有效的用户ID(UID)会被更改为较低的特权值,并将有效用户ID(EUID)保存为保存的用户ID(SUID),以便在任务完成后切换回特权账户。

如果您查看/usr/bin/passwd文件的权限:

代码语言:javascript
复制
-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 权限的可执行文件。

sudo 与 su 的区别

  • 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 可以提供以下功能:

  1. 密码验证: PAM 可以用于确保用户在执行 sudo 命令之前必须通过密码验证。这可以防止未经授权的访问。
  2. 多因素认证: PAM 允许配置多因素认证,要求用户在执行 sudo 命令时提供多种身份验证因素,如密码、智能卡、生物识别等。
  3. 账户控制: PAM 可以检查用户的账户状态,例如是否已锁定或过期,以确保只有合法的用户可以使用 sudo
  4. 日志和审计: PAM 可以记录 sudo 活动,以便审计和跟踪用户操作。
  5. 定制认证方式: PAM 允许管理员根据系统需求选择和配置不同的认证方式,如基于证书的认证、LDAP 集成等。

配置 sudo 与 PAM 结合使用通常涉及编辑 /etc/sudoers 文件,并添加适当的 PAM 模块。以下是一些配置示例:

代码语言:javascript
复制
// 配置 PAM 模块来要求用户提供多因素认证,例如密码和智能卡
auth       required     pam_unix.so
auth       required     pam_google_authenticator.so
// 使用 PAM 模块来检查账户状态,以确保只有合法用户可以使用 `sudo`
account    required     pam_unix.so

sudo-rs 简介

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 团队发现了一个中等严重性问题和两个低严重性问题:

  • CLN-001:相对路径遍历漏洞(中等)
  • CLN-003:Cargo 配置不会剥离(strip)符号(symbol)(低)
  • CLN-004:对 chown 调用的默认权限设置不正确(低)

除了这些发现之外,ROS 还对 sudo-rs 代码库的不同组件进行了模糊测试,但没有发现任何问题。

sudo-rs 源码分析

sudo-rs 项目代码量虽然不是很多,但看上去实现逻辑比想象中的复杂,我是没想到实现 sudo 要这么多代码量。

整体架构

sudo-rssrc 目录包含了多个子目录和文件,这些子目录和文件共同构成了项目的核心功能。以下是 src 目录的结构和内容概述:

  1. common: 包含与 sudo-rs 项目的一些通用功能相关的代码。
  2. cutils: 包含 C 语言实用程序和函数的 Rust 实现。
  3. defaults: 包含处理默认配置和设置的代码。
  4. exec: 包含执行命令和进程管理相关的代码。
  5. log: 包含日志记录功能的实现。
  6. pam: 包含与 PAM (Pluggable Authentication Modules) 相关的代码,用于身份验证和会话管理。
  7. su: 包含实现 su 命令功能的代码。
  8. sudo: 包含实现 sudo 命令功能的代码。
  9. sudoers: 包含解析和处理 sudoers 文件的代码。
  10. system: 包含系统相关的实用程序和功能。
  11. visudo: 包含 visudo 命令的实现,用于编辑 sudoers 文件。
  12. lib.rs: 这是 Rust 项目的入口文件,通常用于模块声明和项目的总体组织。
  13. macros.rs: 包含项目中使用的宏定义。
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-12-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 觉学社 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Rust 研学团简介
  • 我为什么对 sudo-rs 感兴趣
  • 背景:sudo 与 su
    • sudo 与 su 的区别
    • sudo-rs 简介
    • sudo-rs 源码分析
      • 整体架构
      相关产品与服务
      多因子身份认证
      多因子身份认证(Multi-factor Authentication Service,MFAS)的目的是建立一个多层次的防御体系,通过结合两种或三种认证因子(基于记忆的/基于持有物的/基于生物特征的认证因子)验证访问者的身份,使系统或资源更加安全。攻击者即使破解单一因子(如口令、人脸),应用的安全依然可以得到保障。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档