完整性策略實施 (IPE) - 核心文件¶
注意
這是面向開發人員的文件,而不是面向管理員的文件。如果您正在尋找有關 IPE 用法的文件,請參閱IPE 管理指南。
歷史動機¶
最初促使 IPE 實現的問題是建立鎖定的系統。該系統將是天生安全的,並且對可執行程式碼和系統上的特定資料檔案都具有強大的完整性保證,這些資料檔案對其功能至關重要。除非透過完整性策略,否則這些特定資料檔案將不可讀。強制訪問控制系統將存在,因此,xattr 必須受到保護。這導致選擇什麼來提供完整性宣告。當時,考慮了兩種可以保證具有這些要求的系統完整性的主要機制
IMA + EVM 簽名
DM-Verity
兩者都經過仔細考慮,但是選擇使用 DM-Verity 而不是 IMA+EVM 作為 IPE 原始用例中的完整性機制是由於三個主要原因
保護額外的攻擊媒介
使用 IMA+EVM,如果沒有加密解決方案,系統容易受到針對上述特定資料檔案的離線攻擊。
與可執行檔案不同,讀取操作(如對受保護資料檔案的操作)不能強制進行全域性完整性驗證。這意味著必須存在某種形式的選擇器來確定讀取是否應強制執行完整性策略,或者不應強制執行。
當時,這是透過強制訪問控制標籤完成的。IMA 策略將指示哪些標籤需要完整性驗證,這提出了一個問題:EVM 將保護標籤,但是如果攻擊者可以離線修改檔案系統,則攻擊者可以擦除所有 xattr,包括 SELinux 標籤,這些標籤將用於確定檔案是否應受到完整性策略的約束。
使用 DM-Verity,由於 xattr 作為 Merkel 樹的一部分儲存,因此如果對受 dm-verity 保護的檔案系統進行離線掛載,則校驗和不再匹配,並且檔案讀取失敗。
由於使用者空間二進位制檔案已在 Linux 中分頁,因此 dm-verity 還提供了針對惡意塊裝置的額外保護。在這種攻擊中,塊裝置最初報告 IMA 雜湊的相應內容,從而通過了所需的完整性檢查。然後,在訪問實際資料的頁面錯誤上,將報告攻擊者的有效負載。由於 dm-verity 將在頁面錯誤發生時(以及磁碟訪問時)檢查資料,因此可以緩解此攻擊。
效能
dm-verity 在讀取塊時按需提供完整性驗證,而無需將整個檔案讀取到記憶體中進行驗證。
簽名的簡易性
無需兩個簽名(IMA,然後 EVM):一個簽名覆蓋整個塊裝置。
簽名可以儲存在檔案系統元資料外部。
簽名支援基於 x.509 的簽名基礎設施。
下一步是選擇一個策略來實施完整性機制。該策略的最低要求是
策略本身必須經過完整性驗證(防止針對它的簡單攻擊)。
策略本身必須能夠抵抗回滾攻擊。
策略實施必須具有類似 permissive 的模式。
策略必須能夠在不重新啟動的情況下完全更新。
策略更新必須是原子的。
策略必須支援撤銷先前編寫的元件。
策略必須可以在任何時間點進行審計。
當時,IMA 作為唯一的完整性策略機制,根據這些要求進行了評估,但未能滿足所有最低要求。考慮擴充套件 IMA 以滿足這些要求,但最終由於兩個原因而被放棄
迴歸風險;許多這些更改將導致對 IMA 的重大程式碼更改,IMA 已經存在於核心中,因此可能會影響使用者。
IMA 用於系統中的測量和證明;將測量策略與本地完整性策略實施分開被認為是可取的。
由於這些原因,決定建立一個新的 LSM,其職責僅是本地完整性策略實施。
作用和範圍¶
IPE,顧名思義,從根本上講是一種完整性策略實施解決方案;IPE 不強制規定如何提供完整性,而是將該決定留給系統管理員透過他們選擇的適合其個人需求的機制來設定安全標準。有幾種不同的完整性解決方案可以提供不同級別的安全保證;IPE 允許系統管理員為理論上所有這些解決方案表達策略。
IPE 本身沒有固有的機制來確保完整性。相反,有更有效的層可用於構建可以保證完整性的系統。重要的是要注意,證明完整性的機制與實施該完整性宣告的策略無關。
因此,IPE 的設計圍繞
與完整性提供商輕鬆整合。
平臺管理員/系統管理員易於使用。
設計原理:¶
IPE 的設計是在評估其他作業系統和環境中的現有完整性策略解決方案之後進行的。在對其他實現的這項調查中,發現了一些缺陷
策略是人類不可讀的,通常需要二進位制中間格式。
單個不可自定義的操作被隱式地用作預設值。
除錯策略需要手動步驟來確定違反了哪些規則。
編寫策略需要深入瞭解更大的系統或作業系統。
IPE 嘗試避免所有這些缺陷。
策略¶
純文字¶
IPE 的策略是純文字。與其他 LSM 相比,這引入了稍大的策略檔案,但解決了其他平臺上一些完整性策略解決方案出現的兩個主要問題。
第一個問題是程式碼維護和重複的問題。要編寫策略,該策略必須是某種形式的字串表示形式(無論是結構化的,透過 XML、JSON、YAML 等),以使策略作者能夠理解正在編寫的內容。在假設的二進位制策略設計中,需要一個序列化程式將策略從人類可讀的形式寫入到二進位制形式,並且需要一個反序列化程式來將二進位制形式解釋為核心中的資料結構。
最終,將需要另一個反序列化程式才能將二進位制檔案轉換回人類可讀的形式,並儘可能多地保留資訊。這是因為此訪問控制系統的使用者必須保留校驗和的查詢表和原始檔案本身,以嘗試瞭解已在此係統上部署了哪些策略以及未部署哪些策略。對於單個使用者來說,這可能沒問題,因為舊策略幾乎可以在更新生效後立即丟棄。對於管理成千上萬臺(如果不是成千上萬臺)計算機群的使用者,它們具有多個不同的作業系統和多個不同的操作需求,這很快就會成為一個問題,因為幾年前的陳舊策略可能仍然存在,從而很快導致需要恢復策略或資助大量基礎設施來跟蹤每個策略包含的內容。
現在有了三個單獨的序列化器/反序列化器,維護成本變得很高。如果策略避免了二進位制格式,則只需要一個序列化器:從人類可讀的形式到核心中的資料結構,從而節省了程式碼維護並保留了可操作性。
二進位制格式的第二個問題是透明度問題。由於 IPE 根據系統資源的信任控制訪問,因此必須信任其策略才能進行更改。這是透過簽名完成的,從而需要簽名作為流程。作為流程的簽名通常使用高安全標準完成,因為任何已簽名的內容都可用於攻擊完整性實施系統。同樣重要的是,在簽名某些內容時,簽名者要知道他們正在簽名什麼。二進位制策略可能會導致對此事實的混淆;簽名者看到的是不透明的二進位制 blob。另一方面,純文字策略使簽名者可以檢視提交簽名的實際策略。
啟動策略¶
如果配置正確,IPE 能夠在核心啟動並且使用者模式啟動後立即實施策略。這意味著策略需要某種級別的儲存,以便在使用者模式啟動後的那一分鐘應用。通常,該儲存可以透過以下三種方式之一處理
策略檔案位於磁碟上,核心在導致實施決定的程式碼路徑之前載入策略。
策略檔案由引導載入程式傳遞給核心,核心解析策略。
存在一個已編譯到核心中的策略檔案,該檔案在初始化時進行解析和實施。
第一個選項存在問題:核心從使用者空間讀取檔案通常不鼓勵,並且在核心中非常不常見。
第二個選項也存在問題:Linux 支援其整個生態系統中的各種引導載入程式 - 每個引導載入程式都必須支援這種新方法,或者必須有一個獨立的來源。與必要的情況相比,這可能會導致對核心啟動進行更劇烈的更改。
第三個選項是最好的,但重要的是要注意,該策略將佔用已編譯核心的磁碟空間。重要的是使該策略足夠通用,以便使用者空間可以載入新的、更復雜的策略,但也要足夠嚴格,以免過度授權並導致安全問題。
initramfs 提供了一種可以建立此啟動路徑的方式。核心以僅信任 initramfs 的最小策略啟動。在 initramfs 內部,當安裝真正的 rootfs 但尚未傳輸到該 rootfs 時,它會部署並激活一個信任新 root 檔案系統的策略。這可以防止在任何步驟中過度授權,並將核心策略保持在最小的大小。
啟動¶
但是,並非每個系統都使用 initramfs 啟動,因此編譯到核心中的啟動策略將需要一些靈活性來表達如何為啟動的下一階段建立信任。為此,如果我們只是將編譯到其中的策略設為完整的 IPE 策略,則系統構建器可以適當地表達第一階段的啟動要求。
可更新的、無需重啟的策略¶
隨著時間的推移,要求會發生變化(在先前信任的應用程式中發現漏洞,金鑰滾動等)。更新核心以滿足這些安全目標並不總是合適的選擇,因為更新並非總是沒有風險的,而阻止安全更新會使系統容易受到攻擊。這意味著 IPE 需要一個可以從核心外部的源完全更新(允許撤銷現有策略)的策略(允許在不更新核心的情況下更新策略)。
此外,由於核心在呼叫之間是無狀態的,並且從核心空間從磁碟上讀取策略檔案是一個壞主意(tm),因此必須以無需重啟的方式進行策略更新。
為了允許從外部源進行更新,它可能是惡意的,因此此策略需要有一種方法來標識為受信任的。這是透過連結到核心中信任源的簽名來完成的。任意地,這是 SYSTEM_TRUSTED_KEYRING,它是在核心編譯時最初填充的金鑰環,因為這與編譯到其中的策略的作者與可以部署策略更新的實體是相同的期望相符。
反回滾/反重放¶
隨著時間的推移,漏洞被發現,並且信任的資源可能不再被信任。IPE 的策略對此沒有例外。在更正為安全策略之前,可能會出現錯誤的策略作者部署不安全策略的情況。
假設只要不安全策略已簽名,並且攻擊者獲取了不安全策略,IPE 就需要一種方法來防止從安全策略更新回滾到不安全策略更新。
最初,IPE 的策略可以具有 policy_version,該 policy_version 指出可以在系統上啟用的所有策略的最低必需版本。這將防止系統處於活動狀態時的回滾。
警告
但是,由於核心在啟動時是無狀態的,因此此策略版本將在下次啟動時重置為 0.0.0。系統構建器需要注意這一點,並確保在啟動後儘快部署新的安全策略,以確保攻擊者部署不安全策略的機會之窗最小。
隱式操作:¶
只有在考慮系統中多個操作之間的混合安全級別時,隱式操作的問題才會變得可見。例如,考慮一個系統,該系統對可執行程式碼和系統上的特定資料檔案都具有強大的完整性保證,這些資料檔案對其功能至關重要。在此係統中,可能有三種類型的策略
一種策略,其中未能在策略中匹配任何規則會導致操作被拒絕。
一種策略,其中未能在策略中匹配任何規則會導致操作被允許。
一種策略,其中在未匹配任何規則時所採取的操作由策略作者指定。
第一個選項可以使策略像這樣
op=EXECUTE integrity_verified=YES action=ALLOW
在示例系統中,這對於可執行檔案效果很好,因為所有可執行檔案都應該具有完整性保證,沒有例外。問題在於關於特定資料檔案的第二個要求。這將導致這樣的策略(假設每行按順序評估)
op=EXECUTE integrity_verified=YES action=ALLOW
op=READ integrity_verified=NO label=critical_t action=DENY
op=READ action=ALLOW
如果您閱讀文件,瞭解策略是按順序執行的,並且預設設定為拒絕,則這在某種程度上是清楚的;但是,最後一行有效地將該預設值更改為 ALLOW。這是必需的,因為在實際系統中,有一些未經驗證的讀取(想象一下附加到日誌檔案)。
第二個選項,匹配任何規則會導致允許,對於特定資料檔案來說更清楚
op=READ integrity_verified=NO label=critical_t action=DENY
並且,像第一個選項一樣,在執行場景中存在不足,有效地需要覆蓋預設值
op=EXECUTE integrity_verified=YES action=ALLOW
op=EXECUTE action=DENY
op=READ integrity_verified=NO label=critical_t action=DENY
這留下了第三個選項。與其讓使用者聰明地使用空規則覆蓋預設值,不如強制終端使用者考慮對於他們的場景合適的預設值應該是什麼,並明確宣告它
DEFAULT op=EXECUTE action=DENY
op=EXECUTE integrity_verified=YES action=ALLOW
DEFAULT op=READ action=ALLOW
op=READ integrity_verified=NO label=critical_t action=DENY
策略除錯:¶
在開發策略時,瞭解違反了策略的哪一行以降低除錯成本非常有用;將調查範圍縮小到導致操作的確切行。某些完整性策略系統不提供此資訊,而是提供評估中使用的資訊。然後,這需要與策略相關聯以評估出了什麼問題。
相反,IPE 僅發出匹配的規則。這會將調查範圍限制為確切的策略行(在特定規則的情況下)或部分(在 DEFAULT 的情況下)。這減少了在評估策略時觀察到策略失敗時的迭代和調查時間。
IPE 的策略引擎的設計方式還使其對於人類來說很明顯如何調查策略失敗。每一行都按編寫的順序進行評估,因此該演算法對於人類來說非常容易遵循以重現步驟,並且可能導致失敗。在其他調查的系統中,載入策略時會發生最佳化(例如,對規則進行排序)。在這些系統中,需要多個步驟進行除錯,並且在不先閱讀程式碼的情況下,終端使用者可能並不總是清楚該演算法。
簡化的策略:¶
最後,IPE 的策略是為系統管理員設計的,而不是為核心開發人員設計的。IPE 沒有涵蓋單個 LSM 鉤子(或系統呼叫),而是涵蓋操作。這意味著系統管理員無需知道系統呼叫 mmap、mprotect、execve 和 uselib 必須具有保護它們的規則,他們只需知道他們想要限制程式碼執行。這限制了由於缺乏對底層系統的瞭解而可能發生的繞過量;而 IPE 的維護者(作為核心開發人員)可以做出正確的選擇來確定某些東西是否對映到這些操作,以及在什麼條件下對映。
實施說明¶
匿名記憶體¶
在 IPE 中,匿名記憶體的處理方式與任何其他訪問的處理方式沒有任何不同。當使用 +X 對映匿名記憶體時,它仍然會進入 file_mmap 或 file_mprotect 鉤子,但具有 NULL 檔案物件。這會像任何其他檔案一樣提交給評估。但是,所有當前的信任屬性都會評估為 false,因為它們都是基於檔案的,並且該操作與檔案無關。
警告
當核心從使用者空間緩衝區載入資料時(該緩衝區不受檔案支援),kernel_load_data 鉤子也會發生這種情況。在這種情況下,所有當前的信任屬性也會評估為 false。
Securityfs 介面¶
每個策略的 securityfs 樹有些獨特。例如,對於標準的 securityfs 策略樹
MyPolicy
|- active
|- delete
|- name
|- pkcs7
|- policy
|- update
|- version
策略儲存在 MyPolicy inode 的 ->i_private 資料中。
測試¶
IPE 具有用於策略解析器的 KUnit 測試。推薦的 kunitconfig
CONFIG_KUNIT=y
CONFIG_SECURITY=y
CONFIG_SECURITYFS=y
CONFIG_PKCS7_MESSAGE_PARSER=y
CONFIG_SYSTEM_DATA_VERIFICATION=y
CONFIG_FS_VERITY=y
CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y
CONFIG_BLOCK=y
CONFIG_MD=y
CONFIG_BLK_DEV_DM=y
CONFIG_DM_VERITY=y
CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG=y
CONFIG_NET=y
CONFIG_AUDIT=y
CONFIG_AUDITSYSCALL=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_SECURITY_IPE=y
CONFIG_IPE_PROP_DM_VERITY=y
CONFIG_IPE_PROP_DM_VERITY_SIGNATURE=y
CONFIG_IPE_PROP_FS_VERITY=y
CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG=y
CONFIG_SECURITY_IPE_KUNIT_TEST=y
此外,IPE 還有一個基於 python 的整合測試套件,可以測試使用者介面和實施功能。