Operating Systems Security Basics & Unix Access Control
WARNING
第一部分(Operating Systems Security Basics,从英文幻灯片的第1页至第15页)被略过了。
访问控制 (Access control)
- 引用监视器(reference monitor) 仲裁(mediate)对所有资源的访问。
- 原则:完全仲裁原则(complete mediation): 控制所有资源的访问操作请求
访问控制矩阵模型 (Access matrix model)
- 基本抽象概念
- 主体(Subject)
- 受体(Object)
- 权限(Right)
- 矩阵中每一个元胞中的权限域规定了主体(矩阵的行)对受体(矩阵的列)的访问。
授权主体(Principal)与主体(subject)
- 主体是代表某些授权主体执行的应用程序
- 一个授权主体在任何时候都可能是空闲的,或者有一个或多个主体在代表它执行任务。
问题:什么是UNIX中的主体?
问题:什么是UNIX中的授权主体?
客体(object)
- 一个客体是主体可以对其进行操作的任何东西(以主体的权限为中介)。
- 通常而言,客体在访问的过程中是被动的。客体的几个例子:
- 文件
- 目录(或文件夹)
- 内存中的段
- 但是,主体(即进程)也可以是客体,可以对其进行操作
- 杀死、暂停、恢复进程、发送进程间通信等。
UNIX访问控制的基本概念:用户(User)、组(Groups)、文件(Files)和进程(Processes)
- 每个用户账户都有一个唯一的UID
- UID 0表示超级用户(系统管理员)。
- 一个用户帐户可以属于一个或多个组
- 访问控制中的主体是进程
- 进程与
pair<uid,gid>
相关联,例如:(euid, egid), (ruid, rgid), (suid, sgid)。
- 进程与
- 访问控制中的客体是文件
用户(Users)和授权主体(Principals)
系统将人类用户认证成为一个特定的授权主体。
- 从用户到授权主体之间存在一个一对多的映射关系
- 一个用户可以有很多授权主体,但是
- 每个授权主体都与一个唯一的用户相关联
- 这确保了对用户行为的问责
问题:上述内容在UNIX中意味着什么?
客体的构成
- 在UNIX中,几乎所有的对象都被建模为文件(file)
- 文件被安排在一个层次结构(hierarchy)中
- 文件存在于目录(directory)中
- 目录也是文件的一种
- 每个客体都有
- 所有者
- 组
- 12个权限位
- 一组rwx代表所有者的权限,一组rwx代表组的权限,一组rwx代表其他用户的权限。
- suid, sgid, sticky
UNIX中的inode
每个文件都对应于一个inode,inode指示了文件在磁盘上具体位于何处。 在同一个文件系统上唯一。
TIP
- 软链接(Symbolic link)与硬链接(Hard link)
- 硬链接的文件共享同一个inode
- 软链接的文件通过软链接者的inode查找磁盘,找到源文件的路径
UNIX中的目录
非目录文件的基本权限位
r控制了对文件内容的读
- 例如,
read
系统调用
- 例如,
w控制了对文件内容的修改
- 例如,
write
系统调用
- 例如,
Execute controls loading the file in memory and execute
x控制了文件被加载到内存中并执行的权限
- 例如,
execve
系统调用
- 例如,
文件的执行
- 二进制文件(Binary file)与脚本文件(script file)的对比
- 有执行但无读权限,能否运行一个二进制文件?
- 可以。
- 有执行但无读权限,能否运行一个脚本文件?
- 不可以。
- 有读但无执行权限,能否运行一个脚本文件?
- 可以,通过调用脚本文件的解释器(interpreter)
目录文件的权限位
- 读取权限允许人们显示一个目录中的文件名
- 执行权限控制目录的遍历
- 允许人们在目录中查找,从文件名中找到inode#。
chdir
/cd
一个目录需要对这个目录的执行权限
- 写入以及执行权限控制在目录中创建或删除文件
- 删除一个目录下的文件,不需要对该文件有任何权限
- 访问一个由路径名称确定的文件需要在该路径上的所有目录的执行权限
suid, sgid, sticky位
TIP
Q: 在UNIX访问控制中,suid, sgid, sticky位是什么?euid和egid呢?
A(由AI生成):在基于UNIX的系统中,suid、sgid和sticky位是特殊的权限位,可以设置在可执行文件或目录上以控制访问和权限。此外,euid和egid是与UNIX系统中的用户和组身份有关的概念。让我们更详细地探讨一下这些概念:
SUID(Set User ID): 当可执行文件上的SUID位被设置时,它允许文件以文件所有者的权限而不是执行它的用户的权限被执行。这对于授予某些用户临时提升的权限以完成特定任务特别有用。例如,passwd命令需要以高权限执行来修改密码文件,所以它设置了SUID位。
SGID(Set Group ID): 与SUID类似,SGID位允许可执行文件以组所有者的权限而不是执行它的用户的权限执行。当SGID位被设置在一个目录上时,在其中创建的新文件或目录会继承父目录的组所有权(ownership)。这在多个用户需要在一个共享目录中协作处理文件的情况下是很有帮助的。
sticky:sticky位,在一个目录的权限字段中用“t”或“T”表示,主要用于目录。当sticky位被设置时,只有该目录中文件的所有者或root用户可以删除或重命名该文件。它通常被设置在可由多个用户写入的目录上,如/tmp
目录,以防止其他用户未经授权删除或修改文件。
EUID(Effective User ID): EUID代表在UNIX系统上运行的一个进程的有效用户ID。它是一个运行时属性,决定了一个进程在与各种系统资源交互时的权限和访问权。EUID可以与真正的用户ID(UID)不同,这取决于进程的执行方式以及可执行文件上是否设置了SUID位。
EGID(Effective Group ID): 与EUID类似,EGID代表一个进程的有效组ID。它决定了一个进程在与系统资源交互时的组权限和访问权。像EUID一样,EGID可以基于各种因素与真正的组ID(GID)不同。
这些概念对于理解和管理基于UNIX的系统中的访问控制至关重要,允许对权限和用户/组身份进行细粒度的控制。
例子
访问以下文件/目录需要什么权限?
- 读文件:
/d1/d2/f3
- 写文件:
/d1/d2/f3
- 删除文件:
/d1/d2/f3
- 重命名文件: 从
/d1/d2/f3
到/d1/d2/f4
- 读文件:
文件/目录的访问控制通过系统调用实现
- 例如:open(2), stat(2), read(2), write(2), chmod(2), opendir(2), readdir(2), readlink(2), chdir(2), …
三组权限位
- 直觉上:
- 如果用户是一个文件的所有者,那么所有者的r/w/x位适用
- 否则,如果用户属于该文件所属的组,则适用组的r/w/x位
- 否则,其他的r/w/x位适用
问题:可以实现负向授权(negative authorization),即只允许某个特定组的成员不访问某个文件吗?
关于UNIX访问控制中客体的其他问题
- 除了读/写/执行以外的访问权
- 谁可以改变权限位?
- 所有者可以
- 谁可以改变所有者?
- 只有超级用户
- 谁可以改变权限位?
- 与文件无关的权限(Rights not related to a file)
- 影响另一个进程
- 操作,如关闭系统、挂载一个新的文件系统、监听一个低端口
- 传统上保留给root用户
与访问控制相关的安全原则
- 心理上的可接受性(Psychological acceptability)与配置访问控制策略有关
- 故障安全原则(Fail-safe defaults)
- 最小权限原则(Least privilege)
- 完全仲裁原则(Complete mediation)
故障安全原则
- 将访问权限的控制建立在允许而不是排除的基础上。故障安全原则意味着默认的情况是不给予访问权限,而保护方案则确定了允许访问的条件。它的反面是机制(mechanism)试图确定在什么条件下应该拒绝访问,这为安全系统设计提供了错误的心理基础。保守的设计必须基于为什么客体应该是可访问的的角度,而不是为什么它们不应该被访问。
- 例如,使用白名单而不是黑名单。
在一个大型的系统中,一些客体可能得不到充分的考虑,所以将它们的默认权限设置为没有权限是比较安全的。在一个给予明确访问许可的机制中,设计或实现上的错误倾向于以拒绝访问的方式失败,这是一种安全的情况,因为它将很快被发现。另一方面,在一个明确排除访问许可的机制中的设计或实现错误,往往会因为允许访问而失败,这种失败在正常使用中可能不会被注意到。这一原则既适用于保护机制的外部表现,也适用于其基本实现。
TIP
Q: 在访问控制中,满足故障安全的默认值(Fail-safe defaults)指什么?
A(由AI生成):故障安全默认值,也称为安全默认值或默认安全设置,指的是预定义的设置或配置,旨在将系统或设备中的故障或伤害风险降至最低。这些设置是为了在发生意外或不希望发生的情况下提供一个安全和功能状态。
故障安全默认值通常用于各种技术系统,如计算机软件、硬件设备和工业流程。故障安全默认的目的是确保即使出了问题或用户在配置系统时犯了错误,系统也会默认为安全的状态,并将潜在的损害或消极后果降到最低。
例如,在计算机软件中,故障安全默认可能包括限制用户权限以防止意外修改或删除关键文件,禁用可能导致系统不稳定的某些功能或命令,或实施自动数据备份和恢复机制以防止数据丢失。
故障安全默认值的概念与故障安全原则紧密相连。失效安全原则是一种设计理念,其重点是通过设计系统,使其在发生故障或失灵时默认为安全状态,从而使风险最小化并确保安全。
故障安全默认是故障安全原则的一种应用。通过建立优先考虑安全的预定义设置或配置,故障安全默认有助于确保系统或设备在发生意外事件时恢复到最小的伤害或损害的状态。
故障安全原则承认在任何复杂的系统中都可能发生故障或错误,它旨在减轻这些故障的后果。它强调了设计系统的重要性,这些系统可以通过首先防止故障发生或减轻其影响的方式来检测和应对故障,从而将伤害降到最低。
最小权限原则
- 系统中的每个程序和每个用户都应该使用其完成工作所需的最小权限集进行操作。最首要的目的是,这一原则限制了事故或错误可能造成的损害。它还将特权程序之间的潜在互动数量减少到正确操作的最低限度,因此无意的、不需要的或不当的特权使用不太可能发生。“致其所需(need-to-know)”的军事安全规则就是这一原则的一个例子。
完全仲裁原则
- 对每个客体的每一次访问都必须检查其权限。这一原则,如果系统性地应用,是保护系统(protection system)的主要基础。它迫使人们对访问控制有一个全系统的看法,除了正常操作外,还包括初始化、恢复、关闭和维护。它意味着必须设计一个万无一失的方法来识别每个请求的来源。它还要求对权限检查的结果进行怀疑性的审查以提升其性能。如果权限发生变化,这种记忆的结果必须被系统地更新。
主体(Subjects)与授权主体(Principals)
- 访问权限是为用户账户(授权主体)指定的。
- 访问是由进程(主体)执行的
- 操作系统需要知道一个进程是代表哪个用户账户执行的
- 问题:在Unix中是如何做到这一点的?
现代UNIX系统中的进程用户ID模型(Process User ID Model)
- 每个进程有三个用户ID:
- 真实用户ID(real user ID, abbr. ruid)——进程的所有者
- 有效用户ID(effective user ID, abbr. euid)——在大多数访问控制决策中使用
- 保存的用户ID(saved user ID, abbr. suid)
- 和三个组ID:
- 真实组ID(real group ID, abbr. rgid)
- 有效群组ID(effective group ID, abbr. egid)
- 保存的组ID(saved group ID, abbr. sgid)
- 当一个进程是由
fork
创建的:- 它从其父进程中继承了所有三个用户ID
- 当一个进程通过
exec
执行一个文件时- 执行一个文件时,它会保留它的三个用户ID,除非文件的set-user-ID位被设置(在这种情况下,euid和suid被分配给文件所有者的用户ID)。
- 一个进程可以通过系统调用改变用户ID
文件的suid(set-user-ID)/sgid(set-group-ID)的重要性
- 一些操作没有被建模为文件,需要
user id = 0
,例如:- 停止系统
- 绑定/监听“特权端口”(例如小于1024的TCP/UDP端口)
- 非root用户需要这些权限
- 文件级别的访问控制不够细化
- 系统的完整性不仅需要控制谁可以写,还需要控制如何写
带suid(set-user-ID)/sgid(set-group-ID)的程序的安全问题
- 这些程序通常是“set uid root”
- 这违反了最小权限原则:
- 每个程序和每个用户都应该使用完成工作所需的最小权限来操作
- 问题:为什么违反最小权限是不好的?
- 问题:攻击者会如何利用这个问题?
- 问题:如何解决这个问题?
改变有效用户ID(euid)
- 一个执行“set-uid”程序的进程可以尝试放弃其权限;它可以:
- 永久地放弃权限
- 从所有三个用户ID中删除有特权的用户ID
- 暂时取消权限
- 从其euid中删除特权用户ID,但将其保存在其suid中,以后进程可以通过在其euid中恢复特权用户ID来恢复特权。
- 永久地放弃权限
在登录过程中发生的事情
- 在登录过程中验证了输入的密码是否正确之后,它发出了一个
setuid
系统调用 - 然后,登录进程加载shell,给用户一个登录shell
- 用户键入passwd命令来改变他的密码
fork
系统调用创建了一个新的进程,它加载了程序passwd,这个进程由root用户拥有,并且拥有suid(set-user-ID)位。
机制(Mechanism)与政策(Policy)
- “机制与政策的分离”是一个设计原则
- 粗略地说,实现一个灵活的机制,可以配置为支持不同的政策,而不是在实现中硬编码政策。
- 尽可能地推迟决策,把决策留给用户
- 例子:
- X窗口系统的设计者最初明确提出了“机制,而不是政策(Mechanism, not policy)”。
- X提供基元,界面和外观,直到应用层面。
- UNIX的普世哲学:简单灵活的工具
- Linux安全模块是另一个例子
- X窗口系统的设计者最初明确提出了“机制,而不是政策(Mechanism, not policy)”。
违反“机制,而不是政策”的情况
- Eric Steven Raymond在《The Art of Unix Programming》中的“Unix的错误之处”一节中说:
- “但机制而非政策的代价是,当用户可以设置政策时,用户必须设置政策。非技术性的终端用户经常发现Unix的大量选项和界面风格让他们不知所措,于是退而求其次,选择那些至少假装为他们提供简单的系统。”
- “在短期内,Unix的自由放任方法可能会使它失去许多非技术用户。然而,从长远来看,这个‘错误’可能会带来一个关键的优势--因为政策的寿命往往很短,而机制则很长。 因此,反面的反面是,‘机制,而不是政策’的哲学可能使Unix在更多地被一套政策或界面选择所束缚的竞争者淡出人们的视线之后,还能继续保持其相关性。”
“But the cost of the mechanism-not-policy approach is that when the user can set policy, the user must set policy. Nontechnical end-users frequently find Unix's profusion of options and interface styles overwhelming and retreat to systems that at least pretend to offer them simplicity.”
“In the short term, Unix's laissez-faire approach may lose it a good many nontechnical users. In the long term, however, it may turn out that this ‘mistake’ confers a critical advantage — because policy tends to have a short lifetime, mechanism a long one. So the flip side of the flip side is that the “mechanism, not policy” philosophy may enable Unix to renew its relevance long after competitors more tied to one set of policy or interface choices have faded from view.”
违反“机制,而不是政策”的情况,我的观点
- 对安全来说尤其有问题
- “一个非常灵活的、可以广泛配置的安全机制,不仅让终端用户不知所措,而且还非常容易出错。虽然有正确的方法来配置机制来执行一些理想的安全策略,但往往还有很多不正确的方法来配置系统。而且,这种复杂性常常使用户不知所措,以至于该机制根本没有被启用。虽然机制对于实施保护系统是绝对必要的,但只有一个低级别的机制是不够的。”
- 在Li等人的“Usable Mandatory Integrity Protection for Operating Systems”中,IEEE SSP 2007。
对于安全性,需要做灵活性和严格性的权衡。
UNIX访问控制中“机制与政策”的案例研究
- 政策:一个执行设置为Uid的程序的进程可以放弃其权限;它可以
- 永久性地放弃权限
- 暂时取消权限
- 机制:
Setuid
的系统调用
“Setuid Demystified”,载于USENIX Security '02
早期UNIX系统中的访问控制
- 一个进程有两个用户ID:真实用户ID和有效用户ID,还有一个系统调用
setuid
- 系统调用
setuid(id)
- 当有效用户ID为0时,
setuid
将有效用户ID设为真实用户ID设置为参数id
。 - 否则,
setuid
只能将有效用户ID设为真实用户ID。- 永久放弃权限
- 当有效用户ID为0时,
- 一个进程不能临时放弃权限
问题:为何需要setuid(id)
?
System V分支
- 为了启用临时放弃权限功能,添加了保存的用户ID和一个新的系统调用
- 系统调用
seteuid
- 如果euid为0,
seteuid
可以将euid设置为任何用户ID - 否则,可以将euid设置为ruid或suid。
- 将euid设置为ruid,会暂时降低权限。
- 如果euid为0,
- 系统调用
setuid
也被改变- 如果euid为0,
setuid
的功能与seteuid
相同。 - 否则,
setuid
将三个用户的ID都设置为真实的uid
- 如果euid为0,
BSD分支
- 使用ruid和euid,将系统调用从
setuid
改为setreuid
- 如果euid为0,那么ruid和euid可以被设置为任何用户ID
- 否则,ruid或euid都可以被设置为另一个的值。
- 使得一个进程可以交换ruid和euid
现代UNIX系统
- System V和BSD相互影响,它们都有
setuid
、seteuid
、setreuid
,但语义不同。- 一些现代UNIX系统引入了
setresuid
- 一些现代UNIX系统引入了
- 事情变得混乱、复杂、不一致和充满漏洞
- POSIX标准,Solaris,FreeBSD,Linux
受到推荐的改良API
- 三个方法调用(method calls)
drop_priv_temp
drop_priv_perm
restore_priv
- 这方面的教训?
- “机制,而不是政策”对安全来说不一定是个好主意(灵活性不一定是好事)
- 心理上的可接受性原则
- “用户界面的设计应该是为了便于使用(human interface should be designed for ease of us)”
- 用户对其保护目的的心理印象应与机制相匹配