Skip to content

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 表示,每个文件至少需要:

\[ 100 \times 3 = 300 \, \text{bits} \]

如果这些 bits 放在 inode 中,而 inode 通常只有 128 B256 B,300 bits 就可能占 inode 的 15%30%。更糟的是,每新增用户都要更新所有 inode 的权限 bits,不现实。

  • 访问控制列表(ACL, Access Control List):为单个客体单独维护一张用户权限清单,解决权限矩阵臃肿难维护的缺陷。

  • 基于角色的访问控制(RBAC, Role-Based Access Control):将用户(人)与角色解耦,角色与权限直接相关,用户通过拥有一个或多个角色间接地拥有权限,user - rolerole - permission 通常都是多对多关系。

RBAC 的优势
  • 设定角色与权限之间的关系比设定用户与权限之间的关系更直观
  • 可一次性地更新所有拥有该角色用户的权限,提高了权限更新的效率
  • 角色与权限之间的关系比较稳定,而用户和角色之间的关系变化相对频繁
  • 机制与策略分离,设计者负责设定权限与角色的关系(机制),管理者只需要配置用户属于哪些角色(策略)

POSIX 文件权限把用户分为文件拥有者、文件拥有组和其他用户三类,每个文件只需 9 个 permission bits:

\[ 3\ kinds\ of\ permission \times 3\ classes = 9\ 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_ADMINCAP_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 指向栈底首项:0x0800ab00pop ecx; pop ebx; ret片段地址
    • pop ecx:取出 0xe 存入 ecx
    • pop eax:取出 0x24 存入 eax
    • ret 弹出下一个地址 0x08501154 跳转
  • 执行 add eax,ecx; reteax = eax + 0xeret 跳转至 0x02215f80
  • 执行 pop ecx; pop eax; retpop ecx 取出 0x2d 存入 ecx0x41414141 是无效填充值,ret跳转至0x0010bb80
  • 执行sub eax,ecx; reteax = eax - 0x2d,最终运算结果保存在 eax 寄存器
  • 面向跳转编程(JOP, Jump-Oriented Programming):通过篡改函数指针(corrupt function pointer)来串接 gadgets。
示例:栈指针泄露

  • 入口inet_release 函数中 BLR X2 是寄存器跳转,攻击者篡改 X2 指针作为攻击起点。
  • gadget1:从 X1 不同偏移加载 X3/X4/X5BLR X3 跳转至下一代码段。
  • gadget2MOV X0, SP 把栈指针 SP 存入 X0,窃取 SP 原值,BLR X4 继续跳转。
  • gadget3STR 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