可執行性檢查

AT_EXECVE_CHECK execveat(2) 標誌,以及 SECBIT_EXEC_RESTRICT_FILESECBIT_EXEC_DENY_INTERACTIVE 安全位,旨在讓指令碼直譯器和動態連結器強制執行由核心處理的一致的執行安全策略。 參見 samples/check-exec/inc.c 示例。

直譯器是否應該檢查這些安全位,取決於執行惡意指令碼相對於執行環境的安全風險,以及核心是否可以檢查指令碼是否可信。 例如,在伺服器上執行的 Python 指令碼可以使用任意系統呼叫並訪問任意檔案。 這樣的直譯器應該被啟發使用這些安全位,並讓使用者定義他們的安全策略。 然而,在 Web 瀏覽器中執行的 JavaScript 引擎應該已經被沙箱化,因此不應該能夠損害使用者的環境。

為定製執行環境(例如,加固的 Linux 發行版或封閉容器映象)構建的指令碼直譯器或動態連結器可以使用 AT_EXECVE_CHECK,而無需檢查相關的安全位,如果向後相容性由其他東西處理(例如,原子更新確保所有合法的庫都可以執行)。 因此,建議指令碼直譯器和動態連結器預設在執行時檢查安全位,但也提供自定義構建的能力,使其表現得好像 SECBIT_EXEC_RESTRICT_FILESECBIT_EXEC_DENY_INTERACTIVE 始終設定為 1(即始終強制執行限制)。

AT_EXECVE_CHECK

AT_EXECVE_CHECK 標誌傳遞給 execveat(2) 只會對常規檔案執行檢查,如果允許執行該檔案則返回 0,忽略檔案格式以及相關的直譯器依賴項(例如,ELF 庫、指令碼的 shebang)。

程式應始終執行此檢查,以將核心級別的檢查應用於不由核心直接執行而是傳遞給使用者空間直譯器的檔案。 從直譯器的角度來看,所有包含可執行程式碼的檔案都應進行檢查。 但是,此檢查的結果應僅根據 SECBIT_EXEC_RESTRICT_FILESECBIT_EXEC_DENY_INTERACTIVE.強制執行。

此標誌的主要目的是提高執行環境的安全性和一致性,以確保直接檔案執行(例如,./script.sh)和間接檔案執行(例如,sh script.sh)導致相同的結果。 例如,這可以用於根據呼叫者的環境檢查檔案是否可信。

在安全環境中,還應檢查庫和任何可執行依賴項。 例如,動態連結應確保允許執行所有庫,以避免簡單的繞過(例如,使用 LD_PRELOAD)。 為了使這種安全的執行環境有意義,只有可信的程式碼才能執行,這還需要完整性保證。

為了避免導致 time-of-check to time-of-use 問題的競爭條件,AT_EXECVE_CHECK 應與 AT_EMPTY_PATH 一起使用,以針對檔案描述符而不是路徑進行檢查。

SECBIT_EXEC_RESTRICT_FILE 和 SECBIT_EXEC_DENY_INTERACTIVE

當設定了 SECBIT_EXEC_RESTRICT_FILE 時,只有當呼叫 execveat(2),使用相關的檔案描述符和 AT_EXECVE_CHECK 標誌成功時,程序才應解釋或執行檔案。

此安全位可以由使用者會話管理器、服務管理器、容器執行時、沙箱工具等設定。 除了測試環境,相關的 SECBIT_EXEC_RESTRICT_FILE_LOCKED 位也應設定。

程式應僅根據安全位強制執行一致的限制,而不依賴於任何其他使用者控制的配置。 實際上,這些安全位的使用案例是僅信任由系統配置(透過核心)審查的可執行程式碼,因此我們應小心不要讓不受信任的使用者控制此配置。

但是,指令碼直譯器仍然可以使用使用者配置,例如環境變數,只要它不是停用安全位檢查的一種方式。 例如,PATHLD_PRELOAD 變數可以由指令碼的呼叫者設定。 更改這些變數可能會導致意外的程式碼執行,但僅來自經過審查的可執行程式,這是可以接受的。 為了使這有意義,系統應提供一致的安全策略,以避免任意程式碼執行,例如,透過強制執行寫入異或執行策略。

當設定了 SECBIT_EXEC_DENY_INTERACTIVE 時,程序絕不應解釋互動式使用者命令(例如,指令碼)。 但是,如果此類命令透過檔案描述符(例如,stdin)傳遞,如果呼叫 execveat(2),使用相關的檔案描述符和 AT_EXECVE_CHECK 標誌成功時,則應解釋其內容。

例如,使用指令碼片段作為引數呼叫的指令碼直譯器,如果設定了 SECBIT_EXEC_DENY_INTERACTIVE,則應始終拒絕此類執行。

此安全位可以由使用者會話管理器、服務管理器、容器執行時、沙箱工具等設定。 除了測試環境,相關的 SECBIT_EXEC_DENY_INTERACTIVE_LOCKED 位也應設定。

以下是指令碼直譯器根據任何執行安全位的組合的預期行為

  1. SECBIT_EXEC_RESTRICT_FILE=0SECBIT_EXEC_DENY_INTERACTIVE=0

    始終解釋指令碼,並允許任意使用者命令(預設)。

    沒有威脅,每個人和每件事都是可信的,但由於呼叫 execveat(2)AT_EXECVE_CHECK,我們可以先於潛在的問題,指令碼直譯器應始終執行但忽略此呼叫。 實際上,此檢查對於使系統管理員能夠驗證請求(例如,使用審計)併為遷移到安全模式做準備仍然很重要。

  2. SECBIT_EXEC_RESTRICT_FILE=1SECBIT_EXEC_DENY_INTERACTIVE=0

    如果指令碼不可執行,則拒絕指令碼解釋,但允許任意使用者命令。

    威脅是由受信任(且未被愚弄)的使用者執行的(潛在的)惡意指令碼。 這可以防止意外的指令碼執行(例如,sh /tmp/*.sh)。 這對於(半受限)使用者會話是有意義的。

  3. SECBIT_EXEC_RESTRICT_FILE=0SECBIT_EXEC_DENY_INTERACTIVE=1

    始終解釋指令碼,但拒絕任意使用者命令。

    此用例可能對安全服務(即沒有互動式使用者會話)有用,其中指令碼的完整性經過驗證(例如,使用 IMA/EVM 或 dm-verity/IPE),但訪問許可權可能尚未準備好。 實際上,任意互動式命令將更難以檢查。

  4. SECBIT_EXEC_RESTRICT_FILE=1SECBIT_EXEC_DENY_INTERACTIVE=1

    如果指令碼不可執行,則拒絕指令碼解釋,並且還拒絕任何任意使用者命令。

    威脅是由不受信任的使用者(但受信任的程式碼)執行的惡意指令碼。 這對於可能僅執行受信任指令碼的系統服務是有意義的。