查看原文
Linux內核中包含了多個安全子系統,它們之間相互獨立又有着千絲萬縷的聯繫,導致人們對它們往往有一種霧裏看花的感覺。在這篇文章裏,我們對Linux內核中的安全子系統做一個簡單的分析,算是一個入門。
Linux內核的安全子系統大概包括下面幾個:
- 訪問控制(AC,Access Control),它是最常見也是最重要的安全機制。AC主要是要管理Linux下的一個主體(如進程)到底對一個客體(如文件)是否能採取某些訪問操作(如讀取文件內容)。訪問控制又進一步包括:
- 自主訪問控制(DAC),包括訪問控制列表(ACL)以及權能模型(POSIX capabilities)
- 強制訪問控制(MAC),包括很多人都聽説過的SELinux與AppArmor都是MAC
- 用户驗證(Authentication),它主要指的是如何識別一個真實的、物理的人是Linux系統中的一個註冊賬號
- 資源隔離,將進程之間的資源(包括文件、進程、網絡等)隔離開,使得應用程序運行互不影響
- 配額限制,對軟件進行資源配額限制,例如限定某軟件或者某些軟件最多佔用多少資源等
- 系統沙箱,限定應用程序是否能調用某些系統調用,或者以某種參數調用某些系統調用
- 可信計算,對系統的完整性進行校驗,例如從硬件校驗bootloader的完整性,從bootloader校驗內核的完整性等,一般的完整性校驗都是通過預先對原內容進行hash計算得到一個散列值存儲在安全區,再在正式使用數據之前校驗散列值是否有變化的方式來實現的
- 安全審計,在系統運行過程中記錄安全日誌,在安全事件發生後,通過安全審計可以追查當時的場景,定位原因,修補漏洞,以避免再次發生類似的安全問題
- 透明加密,對數據進行多層次的透明加密,以保證在沒有得到密鑰的情況下,被加密保護的數據無法被恢復出明文,而且在得到正確密鑰的情況下,應用程序能像訪問明文數據一樣訪問密文數據
- 網絡防護,即對通過網絡進出本系統的數據進行安全檢查
下面,我們稍微展開説一下各個安全子系統。
訪問控制
在Linux操作系統下,自主訪問控制指的是文件的屬主(owner)可以設置文件被系統中所有用户訪問的權限。
常見的DAC設置命令是chmod,所有用户被劃分為三類,即屬主(u,user),與屬主同組的用户(g,group)以及其它用户(o,others),訪問權限則包括讀(r,read)、寫(w,write)與執行(x,execute),由於用户與訪問權限都是三個,因此一般會使用三個八進制的數字表示權限。
例如將文件file1的權限設置為屬主可讀可寫,同組用户與其他用户可讀,則可以運行chmod 0644 file1,其中6即為二進制的100 + 二進制的10,表示對屬主可讀與可寫,4即為二進制的100,分別表示對同組可讀,以及對其它用户可讀。
上述文件的權限被保存在文件的inode中,進程的安全憑證則是在內核對應的task_struct的struct cred real_cred與struct cred cred中,在打開文件時內核會對inode中的文件權限與進程中的安全憑證進行對比與DAC檢查。這種權限設置方法是從Unix沿襲而來的訪問控制機制。
由於傳統的DAC設置用户分類粒度太粗,因此為了提供細粒度的讀寫執行的訪問控制,Linux又引入了訪問控制列表,可以針對某個用户或者用户組設置單獨的訪問權限,使用的命令是setfacl與getfacl,對應的設置經過編碼保存在文件的擴展屬性system.posix_acl_access中。
在Linux系統下有一個系統管理員賬號,即root。它是一個bug級的存在,普通用户設置的讀寫權限對於root來説是沒有作用的,root可以跳過DAC直接讀取、刪除、修改普通用户的任何文件。也就是説一旦一個人擁有了root權限,他實際上就可以在Linux下為所欲為了。而有些功能既需要訪問系統級的資源,從而需要有root權限,又需要被普通用户使用,因此*nix又發明了setuid,用來將某個屬主為root的可執行程序設置為普通用户可用,在普通用户使用此程序時擁有root的權限,退出此程序時則恢復普通用户的權限。此類程序包括需要創建原始套接字的ping、需要修改/etc/shadow文件等的passwd等。
這種設置帶來的安全風險很大,一旦此類程序中可能存在的安全漏洞被利用,攻擊者即可對整個系統為所欲為。因此,Linux又遵循POSIX的權能模型(capabilities),將傳統的root權限分解為了多個子權限,例如審計、修改屬主、發信號、網絡管理、原始套接字等。這樣,某個原本需要setuid權限的程序可以通過setcap等命令為程序設置相應的最小權能,即使相應的程序被攻擊者利用獲得了特權,攻擊者能獲得的也只有很小的一部分特權,無法為所欲為。
不過,DAC最大的問題是資源的訪問權限控制都是由資源的屬主來設置的,而沒有安全意識的用户往往不知道應該如何設置訪問權限以保證整體安全,畢竟,安全漏洞往往是出在最短板上的。因此,對於DAC,它最大的問題是“不怕神一樣的對手,就怕豬一樣的隊友”。
為了解決豬隊友的問題,強制訪問控制(MAC)被提上了日程。強制訪問控制定義了一整套安全訪問控制的體系,系統管理員(或安全管理員)能夠通過實施MAC,限定遠比DAC更細緻更廣泛的訪問控制。例如在MAC下,我們可以限定即使都是由root啓動,但是隻有由init啓動的nginx才能綁定80端口,但是從bash啓動的nginx則只能綁定8080端口。
最著名的MAC是美國國家安全局(NSA)開發的SELinux,它也是使用最為廣泛的MAC,在Android中也使用到了它。SELinux提供了安全策略,例如基於類型的TE(Type Enforcement)、基於密級的MLS(MultiLevel Security),以及同密級下不同分類的MCS(MultiCategory Security)等,此外,通過角色與用户的劃分,SELinux還提供了基於角色的訪問控制(RBAC)。
不過SELinux雖然可以避免豬隊友的問題,但是它的細粒度管理方式對管理員來説實在是太麻煩了。缺省情況下它提供了幾個用户、十幾個角色、上千個分類、數千個類型、上萬個類型轉換,要正確理解、使用甚至修改這些規則,對於任何管理員來説都是極大的負擔,而且新的軟件仍然在源源不斷地開發出來,舊有的軟件在持續升級與複雜化,這使得事後訪問控制的軟件兼容負擔日益加重。
用户驗證
Linux在用户驗證上提供了一種靈活的機制,那就是PAM(可插拔認證模塊)。
PAM提供了一個所有服務的中心驗證機制,適用於普通登錄、ssh登錄等需要進行身份認證的系統中。在Linux操作系統中存在多個PAM模塊,例如負責使用用户名密碼對用户進行認證的pam_unix.so模塊,負責拒絕用户認證的pam_deny.so模塊,負責通過用户認證的pam_permit.so模塊等。
一般通過文本方式通過本地進入系統使用的程序為login,通過網絡遠程進入系統使用的程序為sshd,通過圖形界面方式通過本地進入系統使用的程序為lightdm。上述的每個負責鑑別用户與登錄的程序都將通過PAM機制對用户進行認證。
login等程序並不進行實質的Linux用户認證,具體的認證方式都是通過Linux系統管理員對PAM模塊的配置完成的。例如最常見的配置是使用上述的pam_unix.so,要求用户輸入用户名與密碼進行認證。但是系統管理員也可以配置pam_fprintd要求用户在使用login或者lightdm登錄的時候通過指紋進行用户認證,而這些認證方式對使用了PAM的login等程序而言,都是透明的。
使用了PAM的優點在於,一方面,將用户鑑別功能從每個應用軟件中獨立出來,單獨進行模塊化設計,實現和維護;另一方面,為這些鑑別模塊建立標準 API,以便各應用程序能方便的使用它們提供的各種功能;同時,鑑別機制對其上層用户(包括應用程序和最終用户)是透明的,便於使用與維護。
PAM採用了分層的模塊式開發,提供了四種類型的模塊:
- 認證管理(auth),負責進行用户認證,這也是PAM模塊的主要功能,它可以提供不同的認證方式,對用户進行組合認證
- 賬號管理(account),負責管理用户賬户的有效性,例如賬户是否過期了,賬户是否可以允許訪問對應的服務等
- 會話管理(session),負責在用户建立會話之前或者銷燬會話之後處理工作,例如記錄審計日誌,或者掛載/卸載用户的家目錄等
- 口令管理(password),負責更新用户認證的機制,例如常見的要求輸入確認密碼的場景,以及要求密碼複雜度的場景
PAM的配置文件通常在/etc/pam.d/下。
模塊將按照在配置文件中列出的順序被調用,這取決於每個條目允許的控制標記(control flag)的值。常見的控制標記值包括:
- required:所有 required 模塊都必須運行到底,如果中間產生了失敗,則失敗信息將會被記錄下來,到最後返回第一個失敗的信息,如果都成功了,則返回成功
- sufficient:如果標記為 sufficient 的模塊返回成功,並且先前沒有 required 或 sufficient 模塊失敗,則忽略剩餘的其餘模塊並直接返回認證成功。
- optional:如果PAM模塊中沒有一個模塊是 required 的,並且沒有任何一個 sufficient 模塊成功,則至少要有一個 optional 模塊返回成功才算成功
實際上,上述的控制標記值只是一個簡化的標記而已,在PAM配置時可以配置數十個參數,例如success、open_err、new_authtok_reqd、default、ignore等,相應的值包括ok、ignore、bad、done、die等。上述的required實際上就是success=ok new_authtok_reqd=ok ignore=ignore default=bad 的縮寫,而sufficient則是 success=done new_authtok_reqd=done default=ignore 的縮寫。
下面是login程序使用到的PAM配置文件(文件名為/etc/pam.d/login)的樣例。
在上述配置文件中,以#開始的每行文字是註釋(已經刪除了大部分),以auth開始的每行文字是認證相關的PAM模塊及其配置,以session開始的每行文字是會話相關的PAM模塊及其配置,而以@include開頭的行則是將其它PAM配置文件的內容導入了本配置文件,這樣可以提供一定的模塊化與較好的可維護性。值得注意的是,這裏的PAM配置文件都是自動生成的,裏面的註釋也比較詳細,可以提供較好的手工修改與管理的基礎。
當前PAM模塊面臨的最主要的問題是:
傳統PAM體系與各個模塊是基於console的,對於圖形界面支持仍需改進
大量新型認證方式(如人臉識別、虹膜識別、指紋識別等)需要我們開發相應的PAM模塊以提供支持
附錄:
(1)https://distrowatch.com/index.php?distribution=deepin
(2)https://www.deepin.org/zh/kernel-security-subsystem-1/