Chapter 10 Security and Protection¶
1 Security Concepts¶
- 电脑安全(Computer security):保护信息和资产的防护措施与策略,目标是在防止盗窃、损坏或自然灾害影响的同时让合法用户仍然能访问并高效使用系统。
- 网络安全(Network Security):防范与监控未经授权的访问、滥用、篡改或拒绝服务行为,针对计算机网络及可通过网络访问的资源。
Network Security 不等于完整 Security
网络层防护只能覆盖经网络访问系统的路径,即使网络边界安全,OS 仍然要处理本地恶意程序、权限绕过、文件访问、内存隔离、设备访问和内核漏洞等问题。
OS 是资源抽象与分配管理器(resource abstractor and allocator),资源的分配离不开管控,而管控的本质就是安全防护。
| OS 概念 | 安全相关机制 |
|---|---|
| CPU | 引入 privileged mode,区分 kernel mode 和 user mode |
| 内存 | 采用 partition(base and limit)和 paging(page table),实现内存隔离 |
| I/O | 引入 access control list,实现权限访问管控 |
Why need security at the OS level?
- 系统中有大量需要保护的数据,OS 必须允许合法访问,同时拒绝非法访问
- 系统中可能运行恶意应用,OS 要限制它们
- OS 自身不可避免会有漏洞,因此需要考虑被局部突破后仍尽量提供保护
Security in Operating System
- 防护对象:CPU、内存、磁盘等硬件资源,各类应用软件程序,以及存储在计算机内的数据与信息
- 防范风险:用户的非授权访问,病毒、蠕虫等程序发起的恶意入侵等
What are the vulnerabilities?
- 物理层面漏洞(Physical vulnerability):如计算机设备被盗
- 自然因素漏洞(Natural vulnerability):如地震等自然灾害损毁设备
- 软硬件漏洞(Hardware / software vulnerability):如软硬件故障失效
- 存储介质漏洞(Media vulnerability):如硬盘被盗
- 通信链路漏洞(Communication vulnerability):如通信线路被窃听搭线
- 人为因素漏洞(Human vulnerability):如内部人员泄密或作恶
- 弱口令漏洞(Password weakness):如密码设置过于简单
- 程序漏洞(Software bugs):如缓冲区溢出攻击
2 System Security Evaluation Criteria¶
2. 1 TCSEC¶
TCSEC(Trusted Computer System Evaluation Criteria) 由美国 DoD 于 1983 年提出,也称 Orange Book。
| Division | 含义 |
|---|---|
| D | Minimal protection |
| C | Discretionary protection |
| B | Mandatory protection |
| A | Verified protection |

2. 2 ITSEC¶
ITSEC(Information Technology Security Evaluation Criteria) 由法国、德国、荷兰和英国等欧洲国家在 1990 年发布,1991 年欧共体发布 1.2 版本。
ITSEC 通过功能性测试和渗透测试检查 IT 安全属性,首次提出了机密性(confidentiality)、完整性(integrity)和可用性 (availability)的概念和 ST(Security Target)的概念,把安全需求分为功能要求和保证要求。
| 要求 | 含义 |
|---|---|
| 功能要求 | 为满足安全需求采取的技术安全措施,例如访问控制、审计、鉴别 |
| 保证要求 | 确保功能正确实现且有效的措施,例如 penetration testing、安全脆弱性分析 |
ITSEC 分别衡量安全功能(F1 - F10)和安全保证(E0 - E6)。
2. 3 CC¶
CC(Common Criteria for IT Security Evaluation) 是通用安全评估标准。1996 年发布 1.0 版,以美国 TCSEC、FC、加拿大 CTCPEC 和欧洲 ITSEC 为基础;1999 年成为 ISO/IEC 15408。
CC 为 IT 产品和系统的安全功能及保证措施提供通用要求,让不同独立安全评估结果具有可比性,为满足要求的产品和系统确定一个可信级别,帮助用户判断产品是否足够安全,以及残余安全风险是否可接受。
2. 4 Chinese Standards¶
- GB17859-1999:计算机信息系统安全保护系统等级划分准则
- GB/T 18336.1-3-2001:信息技术 信息安全技术 信息技术安全性评估准则
- GB/T 20272-2006:信息安全技术 操作系统安全技术要求
- GA/T 388-2002:计算机信息系统安全等级保护操作系统技术要求
- GA/T 390-2002:计算机信息系统安全等级保护通用技术要求
CC/GB17859/TCSEC/ITSEC对比

3 Common Security Concepts¶
3. 1 Trusted Computing Base¶
TCB(Trusted Computing Base) 是为了实现系统安全保护而被信任的所有机制和组件集合,包括软件、硬件和固件(firmware)。
TCB 越大越难保证安全,TCB 应尽量简单,降低被误用和被攻击的机会,更容易验证。
分层系统中,高层依赖低层,低层不依赖高层。如果组件 C 的安全依赖组件 Cj,而 Cj 不安全,则 C 不可能安全。

由于组件的安全几乎全部依托下层实现,因此 TCB 一般包含该组件下方所有层级。
安全防护机制部署的层级越低,TCB 的范围就越小,安全审计与验证工作就越简单。因此越低层能加入有效保护,越可能缩小上层组件需要直接信任的 TCB。
3. 2 Attack Surface¶
攻击面(Attack Surface)是未授权用户可能访问系统并提取数据的所有入口点或攻击向量(attack vectors)的集合,可能来自上层、同层和底层。攻击面越小,系统越容易做好安全防护。
What is the attack surface of OS?
OS 的攻击面包括 system calls、device drivers、file systems、network stack、IPC、interrupts、hardware interfaces 等。
3. 3 Defense in Depth¶
防御纵深(Defense in-depth) 是在系统中放置多层安全管控防护措施,当某一层控制失败或漏洞被利用时,后续层仍能继续阻止攻击或提高攻击成本。

4 Access Control¶
访问控制(Access control) 是按照访问实体的身份限制其访问对象的机制,目标是让不同用户和程序只能访问被授权的数据、应用与系统资源。
简记
- Authentication:识别用户或程序是谁
- Authorization:确定该主体可以访问什么
- Auditing:记录主体做了什么,供之后分析
4. 1 Authentication¶
Authentication(认证) 验证发起访问请求的主体身份。
| 类型 | 示例 |
|---|---|
| Something you know | 密码、手势密码、问题答案 |
| Something you have | USB-key、密码器 |
| Something you are | 指纹、虹膜、步态、键盘输入习惯 |
认证完成后,OS 会给主体分配 identifier。
| System | Identifier |
|---|---|
| Unix | 32-bit number,保存在 cred structure |
| Windows NT | 27-byte number,保存在 kernel access token |
进程与用户之间如何绑定?
- 每个进程的 PCB /
cred中包含uid - 每个进程来自父进程,通常继承父进程的
uid - 用户登录后运行的第一个进程通常是 shell,shell 初始化
uid - Windows 中窗口管理器会扮演类似 shell 的角色
struct cred {
atomic_t usage;
#ifdef CONFIG_DEBUG_CREDENTIALS
atomic_t subscribers; /* number of processes subscribed */
void *put_addr;
unsigned magic;
#define CRED_MAGIC 0x43736564
#define CRED_MAGIC_DEAD 0x44656144
#endif
kuid_t uid; /* real UID of the task */
kgid_t gid; /* real GID of the task */
kuid_t suid; /* saved UID of the task */
kgid_t sgid; /* saved GID of the task */
kuid_t euid; /* effective UID of the task */
kgid_t egid; /* effective GID of the task */
kuid_t fsuid; /* UID for VFS ops */
kgid_t fsgid; /* GID for VFS ops */
};
4. 2 Authorization¶
Authorization(授权) 决定某个身份对特定对象拥有什么权限,可以用授权矩阵(authorization matrix)描述。
- 客体(Object):被访问的资源(文件、目录、设备等)
- 主体(Subject):发起访问的实体(用户、运行中的程序/进程)

完整权限矩阵太大
假设系统有 100 个用户,每种权限用 1 bit 表示,每个文件至少需要:
如果这些 bits 放在 inode 中,而 inode 通常只有 128 B 或 256 B,300 bits 就可能占 inode 的 15% 到 30%。更糟的是,每新增用户都要更新所有 inode 的权限 bits,不现实。
-
访问控制列表(ACL, Access Control List):为单个客体单独维护一张用户权限清单,解决权限矩阵臃肿难维护的缺陷。
-
基于角色的访问控制(RBAC, Role-Based Access Control):将用户(人)与角色解耦,角色与权限直接相关,用户通过拥有一个或多个角色间接地拥有权限,
user - role和role - permission通常都是多对多关系。
RBAC 的优势
- 设定角色与权限之间的关系比设定用户与权限之间的关系更直观
- 可一次性地更新所有拥有该角色用户的权限,提高了权限更新的效率
- 角色与权限之间的关系比较稳定,而用户和角色之间的关系变化相对频繁
- 机制与策略分离,设计者负责设定权限与角色的关系(机制),管理者只需要配置用户属于哪些角色(策略)
POSIX 文件权限把用户分为文件拥有者、文件拥有组和其他用户三类,每个文件只需 9 个 permission bits:
何时检查权限?
open()时根据打开参数和用户组进行权限检查,合法就生成文件描述符 fd- 后续每次文件操作再根据 fd 信息进行检查,不再重复查原文件权限
- 最小特权级原则:要求主体只获得完成任务所需的最小权限。
passwd 命令如何工作?
系统要求普通用户必须能修改自己的密码,但密码数据保存在 /etc/shadow,普通用户无权直接访问,本质是因为文件级权限粒度过粗,由此引入解决方法 setuid。
setuid:在passwd的 inode 中设置 SUID bit,用户执行passwd时,进程临时以文件 owner(通常是 root)的身份运行,执行结束后恢复,这样把提权时间限制在运行该程序期间。passwd程序本身的逻辑负责保证某个用户只能修改自己的密码。
setuid 的安全风险
setuid 并不等于 RBAC,风险在于提权范围经常大于实际需要。
| 项目 | 情况 |
|---|---|
| 必要权限 | 用户能修改 /etc/shadow 或 /etc/passwd 中自己的那一行 |
| 实际权限 | 进程短暂拥有 root 权限,可能访问更多资源 |
如果 passwd 这类 setuid 程序存在漏洞,例如 buffer overflow 允许篡改返回地址,攻击者可能以 root 身份通过 ROP 执行 execv("/bin/sh"),从而获得高权限 shell。
另一种权限控制思路是能力(capability),目标是提供更细粒度的权限控制,解决 root 用户权限过高的问题,例如读取 /foo 文件和写入 /foo 文件等。
- 权限固定:所有权限含义由内核提前定义,用户进程无法自定义新增权限。
- 绑定生效:权限绑定在对应进程,进程创建时赋予,权限不能跨进程随意传递。
- 无索引 ID:不存在 Capability 编号 ID,不能凭 ID 直接查找、操控内核资源。
- 内核存储:权限由一串 bit 标识,存放于进程
cred结构体(内核空间),用户无法伪造。 - 等效 ACL 分组:多种 Capability 自由组合,等价 ACL 中的权限用户组。
- 细粒度优势(Fine-grained):权限管控粒度精细,不用新建大量系统用户组即可灵活授权。
fd V.S. Capability
- 文件描述符 fd 可以看做是一类 Capability
- 用户不能伪造 fd,必须通过内核打开文件
- fd 只是一个指向保存在内核中数据结构的指针
- 拥有 fd 就拥有了对相应文件的某种访问权限
- 同一个文件可以对应不同 fd,权限可以不同
- fd 可以在进程之间传递:
- 父进程传递给子进程,例如
fork()/ pipe - 非父子进程通过
sendmsg()传递 fd
- 父进程传递给子进程,例如
Linux Capability Problems
理想情况下,几十个 capabilities 能均匀拆分 root 权限,但现实中并不理想。
例如 CAP_SYS_ADMIN 占据大量 permission checks,甚至被称为 new root,很多无明显归属的权限检查被放入 CAP_SYS_ADMIN,导致它过大过强。
此外另一个问题是使用混乱,同一类 SCSI ioctl 路径可能检查 CAP_SYS_ADMIN、CAP_SYS_RAWIO 或二者组合,capability 语义和使用边界并不总是清晰。
| 机制 | 优点 | 缺点 |
|---|---|---|
| ACL | 适合大量 objects,容易一次性给主体授予访问多个对象的权限 | 每次访问都可能需要较昂贵的权限检查 |
| Capability | 使用快,常接近 pointer dereference,适合已授权后的快速操作 | 大量 capabilities 难管理,且 capability 必须从某处安全获得 |
许多系统在打开对象时使用 ACL 检查,例如 fopen() / open(),打开成功后用 fd 这类 capability 执行 read() / write() 等后续操作。
4. 3 Auditing¶
Auditing(安全审计)记录用户与程序的全部操作行为,留存日志,用于后续安全核查与分析,是 CC-CAPP / EAL 认证的重要要求。
Linux 审计框架提供 CAPP-compliant auditing system,它可以可靠收集系统上所有安全相关或非安全相关事件的信息。
4. 4 Reference Monitor¶
引用监视器(Reference monitor) 是实现访问控制的一种方式,要求主体必须通过引用(reference)间接访问对象。

引用监视器位于主体和对象之间,负责 authentication 和 authorization,引用监视器机制必须保证其不可被绕过(Non-bypassable)。
设计者必须考虑所有可能访问路径,保证所有路径都必须经过检查。例如,应用必须通过文件描述符访问文件,不能直接访问磁盘上的数据,也不能只凭 inode number 直接读文件内容。此时文件系统就是引用监视器,文件描述符就是引用。
- 自主访问控制(DAC, Discretionary Access Control):对象拥有者可以决定其他人是否能访问该对象。
示例
文件系统是典型 DAC,文件拥有者可以设置文件如何被其他用户访问,例如使用 chmod 修改权限。但是对部分场景(如军队)来说,DAC 过于灵活。
- 强制访问控制(MAC, Mandatory Access Control):系统增加强制的、不可被对象拥有者随意改变的规则。
示例
MAC 由系统强制执行。例如某文件被标记为机密,即使文件拥有者也不能随意把它给没有权限的人看。MAC 可以与 DAC 结合,此时 MAC 优先级更高。
5 Attacks and defenses¶
示例
考虑如下逻辑:
bool admin;
if (admin)
root_access();
else
normal_user_access();
- Code injection attack:直接执行攻击者代码,例如调用
root_access()

- Code reuse attack:不注入新代码,但重新组合已有代码

- Non-control-data attack:不改变控制流,却改变安全决策结果

Summary from grsecurity

Evolution of Attacks and Defenses

- 攻击复杂性指数级增加,攻击难度指数级增加,隐蔽性增加
- 攻击者的直接控制能力缩小,即使控制流被保护,数据攻击仍可能完成提权
5. 1 Code Injection¶
内核代码注入(Code injection attack) 通过漏洞让内核执行攻击者控制的代码,其注入方式包括篡改已有代码、注入新的代码和跳到用户态代码(例如 jump-to-user)。
攻击者可以执行新代码,系统控制能力很强,危害大。早期 Linux 或某些旧 Android 设备中,kernel text 可能是 RWX,更容易受到这类攻击。
| Defense | 含义 |
|---|---|
| W^X | Writable 和 executable 不应同时成立 |
| XN / NX | Data pages 不可执行,例如 2001 XN ARM、NX AMD |
| SMEP / PXN | 特权态不可执行用户态页面,例如 2011 Intel SMEP、ARM PXN |
这些保护通常通过内核页表的保护位实现。页表标记某些页面不可执行,硬件在取指时拒绝执行这些页面中的 bytes。
示例

栈向上增长,缓冲区溢出篡改返回地址,意图跳转到栈顶恶意代码,NX 防护让栈内存不可执行,跳转被拦截,注入攻击失败。
如果攻击者能修改内核页表,就可能去掉不可执行保护,再篡改代码。因此可以通过隔离环境保护内核页表,实现纵深防御。
- Intel VT、SGX
- ARM TrustZone、Hypervisor、SKEE
- RISC-V PMP

5. 2 Code Reuse¶
当系统禁止注入新代码、也禁止修改已有代码后,攻击者可以重用已有代码。
示例

Gadget 是已有代码中的小片段,攻击者通过篡改 control data,把 gadgets 串起来执行。
- 面向返回编程(ROP, Return-Oriented Programming):攻击者能控制栈上的返回地址。每个 gadget 以
ret结束, 攻击者把一串 gadget addresses 放在 stack 上,每次ret都跳到下一个 gadget,这样不需要注入新代码就能拼出攻击逻辑
示例:一条用于计算 0xe + 0x24 - 0x2d 的简易 ROP 链,运算结果存放于 eax 寄存器

- 初始 ESP 指向栈底首项:
0x0800ab00(pop ecx; pop ebx; ret片段地址pop ecx:取出0xe存入ecxpop eax:取出0x24存入eaxret弹出下一个地址0x08501154跳转
- 执行
add eax,ecx; ret:eax = eax + 0xe,ret跳转至0x02215f80 - 执行
pop ecx; pop eax; ret:pop ecx取出0x2d存入ecx,0x41414141是无效填充值,ret跳转至0x0010bb80 - 执行
sub eax,ecx; ret:eax = eax - 0x2d,最终运算结果保存在 eax 寄存器
- 面向跳转编程(JOP, Jump-Oriented Programming):通过篡改函数指针(corrupt function pointer)来串接 gadgets。
示例:栈指针泄露

- 入口:
inet_release函数中BLR X2是寄存器跳转,攻击者篡改X2指针作为攻击起点。 - gadget1:从
X1不同偏移加载X3/X4/X5,BLR X3跳转至下一代码段。 - gadget2:
MOV X0, SP把栈指针 SP 存入X0,窃取 SP 原值,BLR X4继续跳转。 - gadget3:
STR X0,[X1,#0x40]将存有 SP 的X0写入攻击者可控内存,BLR X5跳回原程序。
栈指针 SP 被落地到可控内存,攻击者读取内存即可拿到栈地址,绕过 ASLR 地址随机化。
| 保护返回地址 | 含义 |
|---|---|
| Stack canary | 在返回地址前放置 canary,函数返回前检查是否被覆盖 |
| Randomization | 随机化栈、库、内核等地址,提高定位 gadget 的难度 |
| Shadow stack | 使用受保护的 shadow stack 保存返回地址副本 |
| Intel CET | 2016 年提出的硬件支持,包含 shadow stack 等机制 |
| 保护函数指针 | 示例 |
|---|---|
| Jump checking | MS CFG、LLVM CFI |
| Pointer protection | CPI、PA-based pointer authentication |
| Hardware support | Intel CET、ARM PA |
示例:CFI
CFI(Control-Flow Integrity) 要求间接调用只能跳到合法目标集合,从而限制代码重用攻击可拼接的控制流。
ASLR and KASLR
ASLR(Address Space Layout Randomization) 通过随机化地址空间布局提高攻击难度。
KASLR 是对内核启用地址随机化,使得攻击者准确定位 gadgets 或目标函数的难度大大增加,从而缓解了代码重用攻击
5. 3 Non-Control-Data Attack¶
当控制数据被保护后,攻击者可以转向非控制数据攻击(non-control-data attack)。
非控制数据是返回地址和函数指针之外的数据。攻击者不改变控制流,而是修改安全决策依赖的数据。非控制数据种类繁杂,难以实行统一有效保护,主流操作系统均缺乏对数据攻击的有效防护。
示例:SELinux 绕过

SELinux 尚未初始化完毕时会直接跳转到 allow 分支,跳过整套权限校验,无条件放行所有访问。
攻击者可以抢占系统启动时序,在内核还没把 ss_initialized 置1、SELinux策略未加载前,触发该权限检查函数,直接绕过 SELinux 强制访问控制,不受安全策略约束。
Selected Research and Vulnerabilities

Taxonomy of Run-Time Attacks and Defenses
