LSM是什么?
主、次、獨占LSM模塊
SELINUX – 安全增強的Linux
SMACK – 簡化的強制訪問控制
APPARMOR
TOMOYO
YAMA
SAFESETID
LOCKDOWN LSM
結論
我猜,你讀這篇文章,說明你已經對Linux安全模塊(LSM)有所了解。如果你使用過SELinux或AppArmor,其實就已經用過LSM了。甚至,在你使用的Linux發行版本或Android系統之上,也使用了LSM。
內核5.4版本內,有8個LSM模塊:SELinux、SMACK、AppArmor、TOMOYO、Yama、LoadPin、SafeSetID、Lockdown。還有一些LSM模塊在開發中,比如SARA?和?KRSI,也許不久就會合入Linux內核源碼中。如果你是關注安全的系統或軟件工程師,理解為什么有這么多的LSM模塊是非常值得的。它們有一些是解決通用問題,有一些則是解決特定問題。意識到它們的差異,才能更好地理解Linux的安全特性。
LSM是什么?
一個LSM模塊是直接編譯Linux內核的代碼,利用LSM框架,它可以拒絕某個進程訪問重要的內核對象。這些對象包括:文件、inode、任務控制塊、憑證和進程間通信對象。通過指定允許的交互,安全管理員可以讓攻擊者很難利用程序的缺陷從而攻擊系統的其它部分。
LSM框架的第一個,也是最流行的使用場景是強制訪問控制(MAC)策略。毫無疑問,在內核中實現MAC策略的方法有多種。2001年,美國國家安全局的Peter Loscocco在Linux 2.5?內核峰會上展示了首個實現。Linux Weekly News的Jonathan Corbet后來指出:
經過這么多年的發展,這些標準接口已經形成了LSM框架。截止到5.4內核,該框架已經包含224個hook點,這些hook點包含一個注冊函數的API和為LSM模塊保留受保護內核對象所使用的內存的API。到Linux 2.6版本,LSM框架和SELinux合并到了內核主線中(使用LSM框架,而不是直接在內核代碼中修改)。盡管LSM框架的實現,隨著時間的不斷推移而發生變化,但是它實現對重要內核對象的細粒度訪問控制的基本目標沒有改變。
目前的LSM框架已經允許用戶將多個LSM模塊編譯進內核,存儲在內核的堆棧空間中,并同時使用它們。下圖展示了一個文件打開(open())操作的簡略調用流程圖(假設為3個LSM模塊注冊了hook鉤子函數。
用戶態進程調用open(),打開一個文件;
調度系統調用,使用文件路徑作為獲取內核文件對象的參數。如果參數非法,返回錯誤。
正常的自由訪問控制(Discretionary Access Control)文件訪問權限檢查。如果沒有權限,系統調用終止,返回給用戶錯誤。
如果滿足DAC控制,則LSM框架為每個使能的LSM模塊調用file_opne鉤子函數。任何一個LSM鉤子函數返回錯誤,則系統調用終止,并返回給用戶錯誤。
如果所有的安全檢查通過,則為該進程打開該文件,并返回給用戶態進程一個新的文件描述符fd。
主、次、獨占LSM模塊
對LSM有了初認識之后,我們再來看各個LSM模塊能做什么。首先,我們先看看早期的主LSM模塊:SELinux、SMACK、AppArmor和TOMOYO,它們都是MAC訪問控制策略的實現,從用戶空間加載配置策略。他們都以自己的方式解決相同的問題。
早期的LSM框架一次只能允許加載一個LSM模塊。所有的主LSM模塊都假設自己獨占內核保護對象的指針或標識符。因此,所以一次只能使用一個主LSM模塊。可以在編譯內核時選擇編譯進鏡像,如下圖所示;也可以通過內核命令行參數傳遞。
LSM框架不斷優化,已經消除了主、次LSM模塊之間的區別。現在區分主、次LSM模塊的優選方法是使用LSM_FLAG_EXCLUSIVE獨占標志。一個用戶可以配置多個LSM,只要給其中的一個設置LSM_FLAG_EXCLUSIVE標志即可。
次LSM是將大部分策略直接編碼到內核代碼中。通常情況下,次LSM模塊只有enable/disable選項,而不是將策略文件在系統啟動時從用戶空間加載。
SELINUX – 安全增強的Linux
SELinux最早是在Linux2.6版本合入內核的,RedHat發布的Linux發行版將其作為默認的MAC強制訪問策略。它以功能強大和復雜著稱。
SELinux基于屬性實現,將文件的安全屬性存儲在文件系統的擴展文件屬性中。比如,使用ls -Z /bin/bash文件的安全屬性,如下所示。我們可以看到有四個:冒號分割的屬性,分別代表usertype:level。
?
$ ls -Z /bin/bash -rwxr-xr-x. root root system_ushell_exec_t:s0 /bin/bash
?
SELinux的常用方法是指定主體(在此也就是指user)對某種類型的對象采取什么動作。再看上面的ls的輸出,自由訪問控制(DAC)權限表示所有的用戶都允許讀、執行bash,但使用?SELinux,安全管理員可以進一步指定允許執行或讀取策略文件中的shell_exec_t類型文件的主體。比如說,安全工程師不許web服務器執行shell,因為web服務器易受遠程攻擊。
SELinux使用擴展屬性實現的副作用是,對于那些不支持擴展屬性的文件系統中對象無法保護,比如掛載NFSv4版本的NFS文件系統。
由于SELinux的復雜性和強大功能,可以參考Red Hat’s SELinux User’s and Administrator’s Guide獲取更多信息。
SMACK – 簡化的強制訪問控制
與SELinux一樣,SMACK也是基于文件擴展屬性的MAC實現,是開發者合并到Linux內核中的第二個LSM模塊(2.6.24)。但是與SELinux不一樣的是,SMACK是專為嵌入式系統設計的,對于系統管理員來說更簡單。SMACK是車級Linux(AGL)和Tizen操作系統的默認MAC實現。
APPARMOR
AppArmor是另一種MAC實現,最初由Immunix開發,2.6.36版本合入內核。AppArmor是基于?Debian的系統的主要MAC實現。
除了減少了工具數量和復雜性之外,AppArmor和SELinux最大的不同就是,它是基于Path而不是基于屬性。
基于Path的實現有利有弊。積極的一面是,基于Path的策略可以保護任何文件系統的文件,因為存儲安全信息不需要擴展屬性。甚至可以為不存在的文件指定安全規則,因為這種方式下,可以將Path存儲在配置文件中而無需標注任何實際的文件或目錄。另一方面,最常被提及的負面影響是,因為能夠創建硬鏈接,對于同一個物理文件可能存在多個Path。那么,單個文件的安全策略可能會因為不同的Path而不同,這可能會導致安全漏洞。
TOMOYO
與AppArmor一樣,TOMOYO是另一個基于Path的MAC實現,Linux 2.6.30版本首次合入。TOMOYO是專為嵌入式系統設計的,允許安全管理員在測試時記錄所有的用戶進程交互,從而根據開發、測試期間互相看見的進程才能夠交互。如果使用了TOMOYO策略的系統,落入不可信的用戶或敵對環境中,用戶態進程僅執行那些之前允許的交互,簡化了策略生成。
LOADPIN
LoadPin,是一個次LSM模塊,Linux4.7版本合入,用以保證加載內核的所有文件(內核模塊、固件等)來自相同的文件系統,并期望這樣的文件系統是由只讀的設備提供。這旨在簡化從只讀設備啟動的嵌入式系統,讓其無需對內核模塊進行簽名或檢查。
因為簡單易用,LoadPin能夠簡化某些類型的嵌入式系統的內核免受惡意代碼攻擊的過程。
YAMA
Yama,Linux 3.4合入內核的LSM模塊,旨在收集主內核沒有處理的系統內的DAC安全限制。目前,它支持縮小ptrace()系統調用的范圍,阻止通過已經攻擊成功的用戶進程作為跳板,從相同用戶的其它進程中抽取敏感數據信息。
SAFESETID
SafeSetID是在Linux 5.1版本合入的一個LSM模塊,用來限制將UID/GID轉換成白名單中允許的那些UID/GID。
我認為Linux內核中對SafeSetID使用場景的描述是非常準確的:
This can be used to allow a non-root program to transition to other untrusted uids without full blown?CAP_SETUID?capabilities. The non-root program would still need?CAP_SETUID?to do any kind of transition, but the additional restrictions imposed by this LSM would mean it is a “safer” version of?CAP_SETUID?since the non-root program cannot take advantage of?CAP_SETUID?to do any unapproved actions (e.g. setuid to uid 0 or create/enter new user namespace). The higher level goal is to allow for uid-based sandboxing of system services without having to give out?CAP_SETUID?all over the place just so that non-root programs can drop to even-lesser-privileged uids. This is especially relevant when one non-root daemon on the system should be allowed to spawn other processes as different uids, but its undesirable to give the daemon a basically-root-equivalent CAP_SETUID.
通俗的說就是,如果非特權程序想要生成具有不同uid的進程時,無需賦予其CAP_SETUID能力,而是通過SafeSetID就可以修改uid。
—?Documentation/admin-guide/LSM/SafeSetID.rst
LOCKDOWN LSM
lockdown是Linux 5.4版本合入內核的,實現對kernel的鎖定。啟用了lockdown功能后,就可以通過內核命令行參數鎖定kernel,以便保護其完整性和機密性。當設置lockdown為保護完整性,它的特性就不允許用戶空間修改kernel。這些特性包括:未簽名的內核模塊加載,訪問/dev/{mem,kmem,port},訪問/dev/efi_test,未簽名鏡像的執行,休眠,直接PCI訪問,原始IO端口訪問,原始MSR訪問,修改ACPI表,直接PCMCIA CIS存儲,串行端口的重新配置,不安全的內核模塊參數,不安全的MMIO內存,以及debugfs訪問。當設置lockdown為保護機密性時,所有的完整性保護都被啟用,另外還要禁止的功能有:用戶空間從正在運行的內核中提取潛在的機密信息,例如/proc/kcore訪問,使用kprobe和bpf讀取內核RAM,perf?的不安全使用以及tracefs的使用。
lockdown可以通過SELinux、AppArmor、SMACK、或TOMOYO策略文件實現,這種基于靜態策略的獨立LSM策略文件的實現方式,意味著它可以跨平臺運行,而無關于具體的MAC實現機制。
結論
LSM并不是專門設計用來阻止對進程攻擊的工具。良好的編程實踐,配置管理和內存安全的編程語言才是實現阻止攻擊的工具。但是,當系統中運行的程序存在漏洞時,LSM確實能夠阻止利用漏洞攻擊系統的其它組件。所以說,LSM是Linux系統縱深防御的重要一層,通過理解它們能夠提供什么保護,可以增加對保護系統的哪些部分以及如何實現這些保護有一個更好的理解。
審核編輯:湯梓紅
評論