支援的版本:目前 (17) / 16 / 15 / 14 / 13
開發版本:devel
不支援的版本:12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1

F.38. sepgsql — 基於 SELinux、標籤的強制存取控制 (MAC) 安全模組 #

sepgsql 是一個可載入的模組,支援基於 SELinux 安全策略的基於標籤的強制存取控制 (MAC)。

警告

目前的實作有顯著的限制,並且不會對所有動作強制執行強制存取控制。請參閱第 F.38.7 節

F.38.1. 概觀 #

此模組與 SELinux 整合,以提供高於 PostgreSQL 通常提供的額外安全檢查層。從 SELinux 的角度來看,此模組允許 PostgreSQL 作為使用者空間物件管理器運作。由 DML 查詢啟動的每個表格或函數存取都將根據系統安全策略進行檢查。此檢查是 PostgreSQL 執行的常用 SQL 權限檢查之外的額外檢查。

SELinux 存取控制決策是使用安全標籤做出的,這些安全標籤由字串表示,例如 system_u:object_r:sepgsql_table_t:s0。每個存取控制決策都涉及兩個標籤:嘗試執行動作的主體的標籤,以及要對其執行操作的物件的標籤。由於這些標籤可以應用於任何類型的物件,因此可以(並且使用此模組進行)將儲存在資料庫中的物件的存取控制決策,與用於任何其他類型物件(例如檔案)的相同通用標準進行比較。此設計旨在允許集中式安全策略保護資訊資產,而與這些資產的儲存方式無關。

SECURITY LABEL 陳述式允許將安全標籤指派給資料庫物件。

F.38.2. 安裝 #

sepgsql 只能在啟用 SELinuxLinux 2.6.28 或更高版本上使用。它在任何其他平台上都不可用。您還需要 libselinux 2.1.10 或更高版本和 selinux-policy 3.9.13 或更高版本(儘管某些發行版可能會將必要的規則向後移植到較舊的策略版本中)。

sestatus 命令可讓您檢查 SELinux 的狀態。典型的顯示是

$ sestatus
SELinux status:                 enabled
SELinuxfs mount:                /selinux
Current mode:                   enforcing
Mode from config file:          enforcing
Policy version:                 24
Policy from config file:        targeted

如果 SELinux 已停用或未安裝,您必須先設定該產品,然後才能安裝此模組。

若要建置此模組,請指定 --with-selinux(使用 make 和 autoconf 時)或 -Dselinux={ auto | enabled | disabled }(使用 meson 時)。請確定在建置時已安裝 libselinux-devel RPM。

若要使用此模組,您必須在 postgresql.conf 中的 shared_preload_libraries 參數中包含 sepgsql。如果以任何其他方式載入模組,則該模組將無法正常運作。載入模組後,您應該在每個資料庫中執行 sepgsql.sql。這將安裝安全標籤管理所需的函數,並指派初始安全標籤。

以下範例顯示如何使用安裝的 sepgsql 函數和安全標籤來初始化新的資料庫叢集。根據您的安裝情況調整顯示的路徑

$ export PGDATA=/path/to/data/directory
$ initdb
$ vi $PGDATA/postgresql.conf
  change
    #shared_preload_libraries = ''                # (change requires restart)
  to
    shared_preload_libraries = 'sepgsql'          # (change requires restart)
$ for DBNAME in template0 template1 postgres; do
    postgres --single -F -c exit_on_error=true $DBNAME \
      </usr/local/pgsql/share/contrib/sepgsql.sql >/dev/null
  done

請注意,您可能會看到以下部分或全部通知,具體取決於您擁有的 libselinuxselinux-policy 的特定版本

/etc/selinux/targeted/contexts/sepgsql_contexts:  line 33 has invalid object type db_blobs
/etc/selinux/targeted/contexts/sepgsql_contexts:  line 36 has invalid object type db_language
/etc/selinux/targeted/contexts/sepgsql_contexts:  line 37 has invalid object type db_language
/etc/selinux/targeted/contexts/sepgsql_contexts:  line 38 has invalid object type db_language
/etc/selinux/targeted/contexts/sepgsql_contexts:  line 39 has invalid object type db_language
/etc/selinux/targeted/contexts/sepgsql_contexts:  line 40 has invalid object type db_language

這些訊息無害,應忽略。

如果安裝過程完成且沒有錯誤,您現在可以正常啟動伺服器。

F.38.3. 迴歸測試 #

由於 SELinux 的本質,因此執行 sepgsql 的迴歸測試需要幾個額外的設定步驟,其中一些步驟必須以 root 身分完成。迴歸測試不會由普通的 make checkmake installcheck 命令執行;您必須設定設定,然後手動呼叫測試指令碼。這些測試必須在已配置的 PostgreSQL 建置樹的 contrib/sepgsql 目錄中執行。儘管它們需要建置樹,但這些測試旨在針對已安裝的伺服器執行,也就是說,它們與 make installcheck 而不是 make check 相當。

首先,依照第 F.38.2 節中的說明,在一個可用的資料庫中設定 sepgsql。請注意,目前作業系統的使用者必須能夠以超級使用者身分連線到資料庫,而無需密碼驗證。

第二,建立並安裝迴歸測試的政策套件。sepgsql-regtest 政策是一個特殊用途的政策套件,它提供了一組在迴歸測試期間允許的規則。它應該從政策原始檔 sepgsql-regtest.te 建立,這是使用 make 和 SELinux 提供的 Makefile 來完成的。您需要找到系統上適當的 Makefile;以下顯示的路徑僅為一個範例。(此 Makefile 通常由 selinux-policy-develselinux-policy RPM 提供。)建立完成後,使用 semodule 命令安裝此政策套件,該命令會將提供的政策套件載入到核心中。如果套件已正確安裝,semodule -l 應該會將 sepgsql-regtest 列為可用的政策套件。

$ cd .../contrib/sepgsql
$ make -f /usr/share/selinux/devel/Makefile
$ sudo semodule -u sepgsql-regtest.pp
$ sudo semodule -l | grep sepgsql
sepgsql-regtest 1.07

第三,開啟 sepgsql_regression_test_mode。基於安全考量,sepgsql-regtest 中的規則預設為停用;sepgsql_regression_test_mode 參數啟用啟動迴歸測試所需的規則。可以使用 setsebool 命令開啟它。

$ sudo setsebool sepgsql_regression_test_mode on
$ getsebool sepgsql_regression_test_mode
sepgsql_regression_test_mode --> on

第四,確認您的 shell 是否在 unconfined_t 網域中運作。

$ id -Z
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

如有必要,請參閱第 F.38.8 節,以取得調整工作網域的詳細資訊。

最後,執行迴歸測試指令碼。

$ ./test_sepgsql

此指令碼將嘗試驗證您是否已正確完成所有配置步驟,然後它將執行 sepgsql 模組的迴歸測試。

完成測試後,建議您停用 sepgsql_regression_test_mode 參數。

$ sudo setsebool sepgsql_regression_test_mode off

您可能更喜歡完全移除 sepgsql-regtest 政策。

$ sudo semodule -r sepgsql-regtest

F.38.4. GUC 參數 #

sepgsql.permissive (boolean) #

此參數使 sepgsql 能夠在寬鬆模式下運作,而不管系統設定如何。預設為關閉。此參數只能在 postgresql.conf 檔案或伺服器命令列上設定。

當此參數開啟時,sepgsql 在寬鬆模式下運作,即使一般的 SELinux 在強制模式下運作也是如此。此參數主要用於測試目的。

sepgsql.debug_audit (boolean) #

此參數啟用稽核訊息的列印,而不管系統政策設定如何。預設為關閉,這表示訊息將根據系統設定列印。

SELinux 的安全政策也具有控制是否記錄特定存取的規則。預設情況下,會記錄存取違規,但不會記錄允許的存取。

此參數強制開啟所有可能的記錄,而不管系統政策如何。

F.38.5. 功能 #

F.38.5.1. 受控制的物件類別 #

SELinux 的安全模型將所有存取控制規則描述為主體實體(通常是資料庫的用戶端)和物件實體(例如資料庫物件)之間的關係,每個實體都由安全標籤識別。如果嘗試存取未標記的物件,則該物件將被視為已分配標籤 unlabeled_t

目前,sepgsql 允許將安全標籤指派給綱要、表格、欄位、序列、檢視表和函式。當使用 sepgsql 時,會在建立時自動將安全標籤指派給支援的資料庫物件。此標籤稱為預設安全標籤,並根據系統安全政策決定,該政策將建立者的標籤、指派給新物件的父物件的標籤以及可選的建構物件名稱作為輸入。

新的資料庫物件基本上會繼承父物件的安全標籤,除非安全政策有特殊規則(稱為類型轉換規則),在這種情況下,可能會套用不同的標籤。對於綱要,父物件是當前資料庫;對於表格、序列、檢視表和函式,它是包含的綱要;對於欄位,它是包含的表格。

F.38.5.2. DML 權限 #

對於表格,會根據陳述式的類型檢查所有參照目標表格的 db_table:selectdb_table:insertdb_table:updatedb_table:delete;此外,對於包含 WHERERETURNING 子句中參照的欄位的,以及作為 UPDATE 的資料來源的所有表格,也會檢查 db_table:select,等等。

還會針對每個參照的欄位檢查欄位層級的權限。不僅會對使用 SELECT 讀取的欄位檢查 db_column:select,還會對在其他 DML 陳述式中參照的欄位檢查;還會對使用 UPDATEINSERT 修改的欄位檢查 db_column:updatedb_column:insert

例如,考慮

UPDATE t1 SET x = 2, y = func1(y) WHERE z = 100;

在此,將檢查 t1.xdb_column:update,因為它正在更新,將檢查 t1.ydb_column:{select update},因為它既已更新又被參照,並且將檢查 t1.zdb_column:select,因為它僅被參照。還將在表格層級檢查 db_table:{select update}

對於序列,當我們使用 SELECT 參照序列物件時,會檢查 db_sequence:get_value;但是,請注意,我們目前沒有檢查執行對應函式(例如 lastval())的權限。

對於檢視表,將檢查 db_view:expand,然後將單獨檢查從檢視表擴展的物件上所需的任何其他權限。

對於函式,當使用者嘗試執行函式作為查詢的一部分,或使用快速路徑調用時,將檢查 db_procedure:{execute}。如果此函式是受信任的程序,它還會檢查 db_procedure:{entrypoint} 權限,以檢查它是否可以作為受信任程序的進入點執行。

為了存取任何綱要物件,需要在包含的綱要上具有 db_schema:search 權限。當在沒有綱要限定詞的情況下參照物件時,將不會搜尋沒有此權限的綱要(就像使用者沒有綱要上的 USAGE 權限一樣)。如果存在顯式的綱要限定詞,如果使用者沒有具名綱要上的必要權限,則會發生錯誤。

客戶端必須被允許存取所有參考的資料表和欄位,即使它們源自於後續被展開的檢視表,如此一來,無論資料表的內容以何種方式被參考,我們都能應用一致的存取控制規則。

預設的資料庫權限系統允許資料庫超級使用者使用 DML 指令修改系統目錄,以及參考或修改 TOAST 資料表。當啟用 sepgsql 時,這些操作是被禁止的。

F.38.5.3. DDL 權限 #

SELinux 定義了數個權限來控制每個物件類型的一般操作;例如建立、變更、刪除和重新標記安全標籤。此外,數個物件類型具有特殊的權限來控制其獨有的操作;例如在特定結構描述中新增或刪除名稱條目。

建立新的資料庫物件需要 create 權限。SELinux 將根據客戶端的安全標籤和新物件的建議安全標籤來授予或拒絕此權限。在某些情況下,需要額外的權限。

  • CREATE DATABASE 另外需要來源或範本資料庫的 getattr 權限。

  • 建立結構描述物件另外需要在父結構描述上擁有 add_name 權限。

  • 建立資料表另外需要建立每個個別資料表欄位的權限,就像每個資料表欄位都是一個獨立的頂層物件一樣。

  • 建立標記為 LEAKPROOF 的函數另外需要 install 權限。(當為現有函數設定 LEAKPROOF 時,也會檢查此權限。)

當執行 DROP 指令時,將會檢查要移除的物件是否具備 drop 權限。透過 CASCADE 間接刪除的物件也會檢查權限。刪除特定結構描述中包含的物件(資料表、檢視表、序列和程序)另外需要在結構描述上擁有 remove_name 權限。

當執行 ALTER 指令時,將會針對每個物件類型檢查正在修改的物件是否具備 setattr 權限,但對於附屬物件(例如資料表的索引或觸發程序)除外,這些權限將改為在父物件上檢查。在某些情況下,需要額外的權限。

  • 將物件移動到新的結構描述另外需要在舊的結構描述上擁有 remove_name 權限,並在新的結構描述上擁有 add_name 權限。

  • 設定函數的 LEAKPROOF 屬性需要 install 權限。

  • 在物件上使用 SECURITY LABEL 另外需要物件針對其舊的安全標籤的 relabelfrom 權限,以及物件針對其新的安全標籤的 relabelto 權限。(如果安裝了多個標籤提供者,並且使用者嘗試設定安全標籤,但該標籤並非由 SELinux 管理,則應僅檢查 setattr。由於實作限制,目前尚未完成此操作。)

F.38.5.4. 受信任的程序 #

受信任的程序類似於安全定義者函數或 setuid 指令。SELinux 提供了一項功能,允許受信任的程式碼以與客戶端不同的安全標籤執行,通常是為了提供對敏感資料的高度控制存取(例如,可能會省略行,或者可能會降低儲存值的精度)。函數是否作為受信任的程序運作,由其安全標籤和作業系統安全策略控制。例如:

postgres=# CREATE TABLE customer (
               cid     int primary key,
               cname   text,
               credit  text
           );
CREATE TABLE
postgres=# SECURITY LABEL ON COLUMN customer.credit
               IS 'system_u:object_r:sepgsql_secret_table_t:s0';
SECURITY LABEL
postgres=# CREATE FUNCTION show_credit(int) RETURNS text
             AS 'SELECT regexp_replace(credit, ''-[0-9]+$'', ''-xxxx'', ''g'')
                        FROM customer WHERE cid = $1'
           LANGUAGE sql;
CREATE FUNCTION
postgres=# SECURITY LABEL ON FUNCTION show_credit(int)
               IS 'system_u:object_r:sepgsql_trusted_proc_exec_t:s0';
SECURITY LABEL

上述操作應由管理員使用者執行。

postgres=# SELECT * FROM customer;
ERROR:  SELinux: security policy violation
postgres=# SELECT cid, cname, show_credit(cid) FROM customer;
 cid | cname  |     show_credit
-----+--------+---------------------
   1 | taro   | 1111-2222-3333-xxxx
   2 | hanako | 5555-6666-7777-xxxx
(2 rows)

在這種情況下,一般使用者無法直接參考 customer.credit,但受信任的程序 show_credit 允許使用者列印客戶的信用卡號碼,其中某些數字被遮罩。

F.38.5.5. 動態網域轉換 #

如果安全策略允許,可以使用 SELinux 的動態網域轉換功能將客戶端程序的安全標籤(客戶端網域)切換到新的內容。客戶端網域需要 setcurrent 權限,以及從舊網域到新網域的 dyntransition 權限。

應仔細考慮動態網域轉換,因為它們允許使用者根據自己的選擇,而不是像受信任的程序那樣由系統強制規定來切換其標籤,因此也切換其權限。因此,只有在用於切換到權限集小於原始權限集的網域時,dyntransition 權限才被認為是安全的。例如:

regression=# select sepgsql_getcon();
                    sepgsql_getcon
-------------------------------------------------------
 unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
(1 row)

regression=# SELECT sepgsql_setcon('unconfined_u:unconfined_r:unconfined_t:s0-s0:c1.c4');
 sepgsql_setcon
----------------
 t
(1 row)

regression=# SELECT sepgsql_setcon('unconfined_u:unconfined_r:unconfined_t:s0-s0:c1.c1023');
ERROR:  SELinux: security policy violation

在上面的範例中,我們被允許從較大的 MCS 範圍 c1.c1023 切換到較小的範圍 c1.c4,但切換回去被拒絕。

動態網域轉換和受信任的程序的組合啟用了一個有趣的用例,適用於連接池軟體的典型程序生命週期。即使您的連接池軟體不允許執行大多數 SQL 指令,您也可以允許它使用受信任的程序中的 sepgsql_setcon() 函數切換客戶端的安全標籤;這應採用一些憑證來授權切換客戶端標籤的請求。之後,此會話將具有目標使用者的權限,而不是連接池器的權限。連接池器稍後可以再次使用 sepgsql_setcon() 並帶有 NULL 參數,同樣從具有適當權限檢查的受信任程序中調用,來恢復安全標籤的變更。這裡的重點是只有受信任的程序實際上有權限變更有效的安全標籤,並且只有在給予適當的憑證時才會這樣做。當然,為了安全的操作,憑證儲存(資料表、程序定義或任何東西)必須受到保護,以防止未經授權的存取。

F.38.5.6. 其他 #

我們全面拒絕 LOAD 指令,因為任何載入的模組都可能輕易規避安全策略的強制執行。

F.38.6. Sepgsql 函數 #

表 F.30 顯示了可用的函數。

表 F.30. Sepgsql 函數

函數

描述

sepgsql_getcon () → text

返回客戶端網域,即客戶端的目前安全標籤。

sepgsql_setcon ( text ) → boolean

如果安全策略允許,則將目前會話的客戶端網域切換到新的網域。它也接受 NULL 輸入,作為轉換到客戶端原始網域的請求。

sepgsql_mcstrans_in ( text ) → text

如果 mcstrans 常駐程式正在執行,則將給定的合格 MLS/MCS 範圍轉換為原始格式。

sepgsql_mcstrans_out ( text ) → text

如果 mcstrans 常駐程式正在執行,則將給定的原始 MLS/MCS 範圍轉換為合格格式。

sepgsql_restorecon ( text ) → boolean

為目前資料庫中的所有物件設定初始安全標籤。 參數可以是 NULL,或是作為系統預設規格檔案的替代方案的規格檔案名稱。


F.38.7. 限制 #

資料定義語言 (DDL) 權限

由於實作限制,某些 DDL 操作不會檢查權限。

資料控制語言 (DCL) 權限

由於實作限制,DCL 操作不會檢查權限。

資料列層級存取控制

PostgreSQL 支援資料列層級存取,但 sepgsql 不支援。

隱蔽通道

sepgsql 不會試圖隱藏特定物件的存在,即使使用者不允許參考它。 例如,我們可以推斷出一個不可見物件的存在,因為主鍵衝突、外鍵違規等等,即使我們無法取得物件的內容。 最高機密的資料表的存在無法隱藏;我們只希望隱藏其內容。

F.38.8. 外部資源 #

SE-PostgreSQL 介紹

此 Wiki 頁面提供簡要概述、安全設計、架構、管理和即將推出的功能。

SELinux 使用者和管理員指南

本文件提供廣泛的知識,以便在您的系統上管理 SELinux。 它主要關注 Red Hat 作業系統,但不限於它們。

Fedora SELinux 常見問題

本文件回答有關 SELinux 的常見問題。 它主要關注 Fedora,但不限於 Fedora。

F.38.9. 作者 #

KaiGai Kohei

提交更正

如果您在文件中發現任何不正確、與特定功能的使用經驗不符或需要進一步澄清的地方,請使用此表單回報文件問題。