系統調用是唯一訪問操作系統對象的途徑
- 拒絕越權訪問 →→ 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:
在計算機系統設計的初期,真的沒有安全可言——但隨著需求的增長,今天我們已經有非常成熟的安全機制,
從軟件到硬件層層保障系統的安全;而用出其不意的方法攻破這些系統也成為了非常有趣的挑戰。