[OS_26] 计算机系统安全 | CIA原则 | 侧信道攻击
系统调用是唯一访问操作系统对象的途径
- 拒绝越权访问 →→ Confidentiality
- 拒绝越权修改 →→ Integrity
- (再加上公平资源调度 →→ Availability)
在操作系统 API 上,我们可以构建命令行工具、编译器、数据库、浏览器等丰富的应用。
当越来越多用户开始共享计算机、越来越多的应用出现在操作系统中
隔离用户的权限就成为了非常重要的需求,“黑客” 也登上了历史的舞台。
本文内容:现代操作系统中的访问控制。
26.1 计算机系统安全
PC “裸奔” 时代
8086, Real-Mode
- 16-bit CS, 16-bit IP, PC = (CS << 4) + IP (1 MB 寻址能力)
- Firmware code 直接映射到地址空间中
-
- int $x →→ ((void(*)())(x×4x×4))();
- 16-bit 时代的 “系统调用”
BIOS 是计算机的“开机管家”,负责唤醒硬件并启动系统,现已被更强大的 UEFI 取代,但仍是理解计算机启动原理的基石。
完全没有任何安全可言
- 任何程序都可以访问任何硬件
-
- 病毒:复制自己,然后感染更多的计算机 (“加壳”)
- 例子:CIH 能破坏硬件的病毒
CIH病毒是一种能够严重破坏计算机系统的恶意软件,它主要通过以下方式造成危害:
- 感染传播:通过受感染的文件传播,一旦用户运行这些文件,病毒就开始在系统中活动。
- 隐藏自己:病毒会隐藏自身以避开检测。
- 定时触发破坏:设定特定日期(如每月26日),到达该日期时病毒开始行动。
- 数据与硬件破坏:
-
- 破坏硬盘上的数据,导致文件丢失或损坏。
- 最严重的是,某些版本的CIH病毒还会尝试向计算机主板上的BIOS芯片写入数据。BIOS是计算机启动时首先执行的程序,负责初始化硬件并启动操作系统。如果BIOS被破坏,计算机会无法正常启动。
简而言之,CIH病毒不仅会删除你的数据,还可能让你的电脑无法启动,需要专业维修才能恢复正常。不过现在由于技术进步,这种病毒已不多见。
安全不裸奔:Confidentiality
不想给别人看的,别人就看不到
(快速格式化:这个问题我懂)
安全不裸奔:Integrity
不想让别人改的,别人就改不了
(学长:“如何通过入侵老师邮箱拿到期末考卷和修改成绩”bush)
安全不裸奔:Availability
属于我的,别人不能让我用不了
- “Denial-of-service” 攻击
-
- Fork bomb:
:(){ :|: & };:
(之前在讲进程 fork 时,有讲到过[OS_5] 程序和进程 | fork | execve | 浅谈win的api) - Algorithmic complexity attack; 例子:Hash table
- Fork bomb:
漏洞本质
- 攻击原理:攻击者通过发送大量特殊构造的HTTP请求,使服务器CPU资源耗尽(俗称“累死服务器”)。(让 hash 由 o1 退化为 o(n), 被累死)
- 影响对象:主要针对 Apache Tomcat 服务器(一种常用的网站后台程序)。
-
- Distributed DoS (DDoS)
DDoS,即分布式拒绝服务攻击,是一种网络攻击方式
- 想象一下你正在开一家商店,正常情况下顾客们一个接一个地进来购物。
- 但是有一天,一大群人突然一起涌到你的店门口,假装要买东西但实际上并不购买任何东西,只是堵在门口让真正的顾客无法进入。
- 这样一来,你的生意就无法正常进行,因为这些“假顾客”占用了所有的入口资源。
DDoS攻击就是类似的情况,只不过它发生在网络世界里。
攻击者利用控制的大量计算机(称为僵尸网络/肉机)同时向目标服务器发送大量的请求或数据包,这些请求像那群堵在店门口的“假顾客”一样,占用服务器的所有资源或带宽,使得正当用户的请求无法得到处理,最终导致网站或服务变得极慢甚至完全不可用。
这种攻击方式通过分布式的手段放大攻击效果,使得防御变得更加困难。
安全是个巨大的主题
软件 + 硬件协同设计 IEEE S&P (Oakland) 2025
- 分页机制和进程隔离
- 系统调用和访问控制
- 鉴权与授权
- 加密
- 审计与日志
- 机密计算 (TEE)……
一个问题
- 操作系统的设计者,如何在 “功能” 之上实现 Confidentiality, Integrity, Availability?
🛡️ 1. 保密性(Confidentiality)
- 意思:只有授权的人才能看到数据。
- 操作系统怎么做:通过用户权限管理和加密技术,确保只有你授权的人才能访问你的文件。
- 比如:就像银行保险库只允许有钥匙的人打开,别人看不到你存了什么。
🔐 2. 完整性(Integrity)
- 意思:数据不能被未经授权的人篡改。
- 操作系统怎么做:使用权限控制、数字签名和校验机制,防止恶意程序或用户修改关键数据。
- 比如:就像银行会记录每次存取款,并防止有人偷偷改账本。
🚪 3. 可用性(Availability)
- 意思:系统和数据在需要时必须能用。
- 操作系统怎么做:通过资源管理、防崩溃机制和权限控制,保证合法用户随时可以访问所需资源。
- 比如:就像银行虽然安保严格,但还是要让客户顺利办理业务,不能无缘无故关门。
总结
操作系统在提供各种功能(比如运行程序、存储文件)的基础上,通过权限控制、加密、资源管理和安全机制,来保障数据“不被偷看、不被乱改、还能正常使用”,这就是实现 保密性、完整性、可用性 的核心思想。
26.2 访问控制
访问控制
进程 + 虚拟内存已经实现了隔离
- 进程只能以 ELF 规定的权限访问自己的虚拟地址空间
- 系统调用是唯一访问操作系统对象的途径
-
- (假设,内核没有被漏洞攻破)
- 操作系统还有虚拟化机制:虚拟机、容器 (cgroups, namespaces, ...)
访问控制:限制程序对操作系统对象的访问
- 拒绝越权访问 →→ Confidentiality
- 拒绝越权修改 →→ Integrity
- (再加上公平资源调度 →→ Availability)
访问控制原理:一张表
进程 | 对象 | 访问 | 权限 |
1 | /etc/passwd | read | √ |
1 | /etc/passwd | write | √ |
4132 | /etc/passwd | write | × |
4132 | /tmp/hello.txt | write | √ |
“谁能怎么访问什么”
- 越权访问,直接返回 EACCESS (Permission denied)
- 缺点:这个表非常大,而且很难维护
-
- 我们需要一个更简单的机制
UNIX: 用整数表示身份
uid, gid, mode
- uid = 0 →→ root, 其他都是 “普通用户”
-
- root 可以访问所有对象,也可以 setuid
- 子进程继承父进程的 uid
- gid “完全自由” (虽然一般 0 是 root)
-
- 一个用户可以属于多个组
- mode: r, w, x 的权限
-
- 例子:owner 只写不可读,audit 组可以读的日志文件
操作系统完全看不到用户名
- 通过 setuid, setgid, chmod 系统调用实现访问控制
/etc/passwd: 每行一个用户
username:password:uid:gid:comment:home:shell
- 现代系统通常使用 shadow 文件存储密码的 hash
- chsh, passwd 只是直接修改了文件
-
- 操作系统就真的只管 uid,不管如何解读 “用户”
UID:没有那么简单
没有 system (abstraction) 能逃脱成为 💩山
(因为随着各种场景和各种功能的添加(悲
- Real uid (ruid)
- Saved uid (suid)
-
- 为了实现 “恢复权限” 而设计
- Effective uid (euid)
-
- 这是实际访问控制使用的 uid
- Filesystem uid (fsuid)
-
- (Since Linux 1.2,已经没人用了 )
- chmod +s (ls -l /bin/passwd)
- Setuid demystified
核心问题
setuid
是Unix系统的关键功能,允许程序临时提升用户权限(例如普通用户运行passwd
命令修改密码时需管理员权限)。但该机制存在严重安全风险:
- 权限滥用:攻击者可能利用代码漏洞劫持高权限进程。
- 复杂性:开发者难以全面预测
setuid
程序的所有行为路径。
论文贡献
- 形式化建模
首次用数学方法严格定义setuid
的行为规则,建立权限传递模型,明确权限何时生效、何时失效。 - 漏洞自动化检测
开发工具自动扫描setuid
程序,识别以下风险:
-
- 权限未及时撤销(如执行后未降权)
- 非预期权限继承(如子进程意外继承高权限)
- 实践验证
对真实系统(如Solaris、Linux)的常用setuid
工具(如sudo
、mount
)进行测试,发现多个未知漏洞,并给出修复方案。
回到访问控制
进程 | 对象 | 访问 | 权限 |
4132 | /etc/passwd | write | × |
uid, gid, mode 并不是实现访问控制的唯一方法
- Access Control List (ACL)
-
- 基于 xattr 实现,支持为任意数量的用户和组设置权限
- SELinux/AppArmor
-
- sudo apparmor_status | ag --gpt -q Explain
- Capabilities
-
- capsh --drop=cap_net_raw -- -c 'ping 127.0.0.1' (注意这是 fail on execve; getcap 查看 capabilities)
https://github.com/lvy010/operating-system_code/tree/main/security/login
login:
“用户” 并没有什么神奇的——在早期 UNIX 的设计中,它就是一个为进程维护的编号,甚至用户名和密码都只是存放在文本文件中的字符串。
https://github.com/lvy010/operating-system_code/tree/main/security/suid-file
setuid file:
- 通过将二进制文件设置为 setuid 和 root 用户/组,可以实现普通用户以 root 用户身份执行该文件。
- 这个危险的特性带来很多潜在的安全漏洞——因此 bash 在检测到这种行为时,会自动丢弃权限。
26.3 意料之外,之外,之外……
系统安全:攻与防
攻破一个进程
Undefined behavior 不是和大家开玩笑的 😈
- Tutorial (Memory error 贡献了巨量的内核漏洞)
64位栈溢出攻击:
核心原理:
1️⃣ 程序有个"包裹柜"(buffer数组),但管理员未检查包裹大小
2️⃣ 攻击者故意发送超大的"包裹"(300个A字符)
3️⃣ 包裹溢出柜子,覆盖了原本存放"收货地址"的位置(返回地址RIP)
关键步骤:
技术:
- 精确计算溢出长度(264字节填充 + 6字节地址)
- 通过泄露的buffer地址(printf输出)定位攻击位置
- 巧妙处理64位地址限制(必须小于0x00007fffffffffff)
- 使用自制shell code实现读取敏感文件
- 应对GDB与实际环境地址偏移问题
防御启示:
- 启用栈保护编译选项(-fstack-protector)
- 使用地址随机化(ASLR)
- 避免使用危险函数(如strcpy)
这个攻击就像通过篡改快递单号,让快递员把货物送到黑客的仓库,从而窃取数据。
The purpose of this paper is to learn the basics of 64 bits buffer overflow. 文档文档详细演示了从溢出到获取敏感信息的完整攻击链。
实验
https://github.com/lvy010/operating-system_code/tree/main/security/buf-overrun
buffer-overrun:
- 我们 “去掉” 所有的编译保护,就能体验到缓冲区溢出带来的 “灾难性后果”:
- 我们可以把一段代码注入到缓冲区中,然后利用覆盖的返回地址跳转到任意的代码——我们就获得了这个进程所拥有的一切权限。
防御一个进程
我们至少可以减少攻击面
- www-root, ASLR: mmap
-
- 映射到随机的地址
- Canary (stack protector)
- NX-bit (no execute)
- CFI (endbr64,就像是矿井当中碰到少量一氧化碳 就会报警的金丝雀), ...
- CFI:确保程序只能走预设的路线,不能随意跳转。
endbr64
:在特定位置(如间接调用处)增加检查,确保程序不会被重定向到非法代码。
两者结合,就像是给软件穿上了一层坚固的盔甲,抵御那些试图改变程序正常运行路径的攻击。
- LLM 能帮助我们理解和定义“预期行为”,并检测或控制程序是否真的在按预期运行。
- 在未来,LLM 不仅是观察者,还可以作为“决策控制器”,指导操作系统或应用程序只按预期方式运行。
- 比如:AI 决定哪些进程可以通信、哪些资源可以访问。
- 在 LLM 时代,“程序只能按预期方式运行”不再是一个理想,而是可以通过 AI 自动建模、分析和控制的新机遇。
访问控制:也没能完全解决安全问题
“单次” 看起来合法的访问,也可能存在非法行为
- Tenex: Authentication system call
int check_password(__user char *given_pass) {...for (i = 0; i <= strlen(correct_pass); i++)if (correct_pass[i] != given_pass[i]) {sleep(3);return EACCESS; // access denied}return 0;
}
看似精妙的设计,实际……
软件没问题,硬件也可以有漏洞
Meltdown
raise_exception(); // even an HTM abort
uint8_t volatile x = probe_array[data * 4096];
- Timing side channel
-
- Tenex: 天道好轮回
- 现在的办法:KPTI (Page Table Isolation)
-
- 改写了教科书
- Timing Side Channel:通过观察程序执行时间差异来推测敏感信息的攻击手段。
- “Tenex”:安全问题和攻击手法的不断循环与进化。
- KPTI:一种通过隔离用户空间和内核空间内存页表来防止计时侧信道攻击的有效方法。就像是在两个房间之间建一堵墙,保护内核的秘密不被轻易窥探。
你甚至看不见你的对手在哪 (1)
- 超视距攻击:天线和显示器相距 10m,间隔三层石膏板
-
- Electromagnetic eavesdropping risks of flat-panel displays
电磁窃听风险与平面显示器
主题
讨论了平面显示器的电磁窃听风险,回顾了电磁窃听的历史、技术以及防护措施
重点在于如何通过电磁辐射获取敏感信息,以及如何增强显示器的安全性。
关键点
- 电磁窃听的历史
-
- 1914年,德国军队首次利用真空放大器监听敌方电话信号,标志着电磁窃听的早期应用
- 军事和外交通信设施的保护措施,如“红/黑分离”和设备屏蔽,已成为标准
- 电磁辐射与窃听技术
-
- 1985年,Wim van Eck展示了如何通过修改电视接收器窃听视频显示内容
- 现代技术如“TEMPEST”计划,专注于对计算机和通信设备的电磁辐射进行研究和标准化
- 显示器的电磁特性
-
- 阴极射线管(CRT)显示器在高频带宽下放大视频信号,可能作为不良天线发射电磁辐射
- 研究表明,通过适当的频率和带宽设置,可以有效恢复显示内容
- 防护措施
-
- 采用低通滤波器对字体进行处理,减少电磁辐射,提升安全性。例如,去掉频谱的30%可以显著降低信号强度,而不会影响用户的使用体验
- 针对平面显示器的电磁辐射,采取了不同的频率和带宽设置来评估风险
总结
强调了平面显示器在电磁窃听方面的潜在风险,以及通过技术手段和设计改进来增强信息安全的重要性。理解这些风险并采取适当的防护措施对于保护敏感信息至关重要。
你甚至看不见你的对手在哪 (2)
- Physical key extraction attacks on PCs
物理侧信道攻击
核心发现:
电脑运行时就像个「多嘴的机器人」,会通过物理信号无意中泄露秘密!
攻击者可以用普通设备(如手机、收音机甚至人手触摸)窃取加密密钥。
三种窃听方式:
攻击原理:
- 声波攻击:CPU运算时电源模块会发出高频噪音(类似线圈嗡鸣),不同运算模式产生不同声纹
- 电流攻击:通过连接电脑的USB/网线屏蔽层,或直接触摸电脑金属部分测量电势变化
- 电磁攻击:用自制天线或普通收音机接收CPU运算时的电磁辐射
惊人案例:
- 用手机录音10分钟可窃取4096位RSA密钥
- 触摸电脑时通过人体电势波动获取密钥
- 10米外通过网线窃听(类似网络监听但更物理)
防御思路:
- 硬件:电磁屏蔽箱/隔音设备(但成本高)
- 软件:改进加密算法执行模式(如随机化运算步骤)
- 日常:避免陌生设备接触电脑金属部分
启示:
即使软件绝对安全,硬件也可能「出卖」秘密。
这种攻击对银行系统、军事设备等有重大威胁,近年成网络安全新战场。
26.4 总结
Take-away messages:
在计算机系统设计的初期,真的没有安全可言——但随着需求的增长,今天我们已经有非常成熟的安全机制,
从软件到硬件层层保障系统的安全;而用出其不意的方法攻破这些系统也成为了非常有趣的挑战。