設定 - SELinux
概要
SELinux (Security-Enhanced Linux) は、Linuxのセキュリティ拡張機能であり、強制アクセス制御 (MAC) の仕組みを提供する。 (Linux 2.6以降でサポート)
外部に侵入されないための仕組みではなく、侵入された後にアクセスできる範囲を最小限に抑えるための仕組みである。
SELinuxの特徴を以下に示す。
- 強制アクセス制御 (MAC)
- 従来の任意アクセス制御 (DAC) に加えて、より厳格なアクセス制御を実現する。
- 最小権限の原則
- プロセスやユーザに必要最小限の権限のみを与えることで、潜在的な被害を制限する。
- ポリシーベースの制御
- システム管理者が定義したセキュリティポリシーに基づいてアクセスを制御する。
- コンテキストラベル
- ファイル、プロセス、ポート等のリソースにセキュリティコンテキストを割り当てる。
- 動作モード
- Enforcing (強制)、Permissive (許容)、Disabled (無効) の3つのモードがある。
- ログ機能
- セキュリティ違反の試みを詳細にログに記録する。
SELinuxの参考書 | |
---|---|
SELinux System Administration 3rd Edition ソフトウェアやユーザ等を保護するための強制アクセス制御(MAC)の実装 |
SELinux Cookbook |
SELinuxの役割
SELinuxは、Linux上で動作するプロセスからファイル等のリソースに対するアクセスを制御するのが主な機能である。
通常のLinuxシステムでは、ユーザやグループのファイルに対するアクセス権で制御されますが、スーパーユーザは特権ユーザとして全てのファイル等にアクセスすることができる。
これに対して、SELinuxは"強制アクセス制御"(MAC: Mandatory Access Control)と呼ばれる方式を採用している。
MACは、スーパーユーザに対しても設定されたアクセス制御を超えた特権を与えることがない。
多くのセキュリティ攻撃がスーパーユーザ権限を奪取することを第一の目的とし、その後の攻撃に繋げていることを考えると、セキュリティ対策として必要な機能といえる。
SELinuxの機能
TE(Type Enforcement)
プロセスがアクセスできるリソースを制限する機能である。
プロセスにドメインを、リソースにタイプを割り当て、その組み合わせごとにアクセス権を設定する。
このアクセス権の設定の集合を、アクセスベクタという。
子プロセス生成時には、基本的には親プロセスのドメインが引き継がれる。
子プロセスのドメインを変更することを、ドメイン遷移と呼ぶ。
RBAC(Role Based Access Controle)
ユーザがアクセスできるリソースを制限する機能である。
ユーザごとにアクセス可能なロールが決まっており、ロールごとにアクセス可能なドメインが決まっている。
TEにより、ドメインごとにアクセス可能なタイプが決まっているため、最終的には、ユーザがアクセス可能なオブジェクトを制御することができる。
RHELでは、全てのLinuxユーザがunconfined_uに対応しており、unconfined_uにはアクセス制限が掛けられない。
したがって、RHELではRBACは意味をなさない。
SELinuxの機能
セキュリティコンテキスト
SELinuxでは、ドメインやタイプ等のことを、セキュリティコンテキストという形で表現する。
セキュリティコンテキストの例を、以下に示す。
- system_u
- ユーザ識別子
- object_r
- ロール識別子
- lib_t
- タイプ(ドメイン)識別子
- s0
- MLS (Multi Level Security) : 情報の機密性
SELinuxユーザ
Linuxユーザとは異なり、Linuxユーザごとに対応するSELinuxユーザが設定されている。
SELinuxユーザの例を、以下に示す。
- unconfined_u
- アクセス制限のないユーザ (RHELでは全てのLinuxユーザがunconfined_uになる)
ロール
ロールの例を、以下に示す。
- object_r
- 一般的なファイルのロールのこと。
- ロールは、ファイルにとって意味は無い。
- system_r
- プロセスのロールのこと。
- /procディレクトリ下のプロセス関連のファイル等にも使用される。
ドメイン
ドメインは、"制限のないドメイン"と"制限のあるドメイン"に大別できる。
プロセスに割り当てられるドメインの例を、以下に示す。
- 制限のないドメイン
- SELinuxによるアクセス制限を受けない。
- つまり、システムが乗っ取られた場合、SELinuxによる防御は意味をなさない。
- 通常のパーミッションによるアクセス制御は行われる。
- unconfined_t
- ログインユーザが起動するプロセスのドメイン。
- initrc_t
- initで開始されたシステムプロセスのドメイン。
- kernel_t
- カーネルプロセスのドメイン。
- 制限のあるドメイン
- 一般的なソフトウェアに割り当てられる。
- これらのドメインは、SELinuxによるアクセス制御がなされる。
- http_t
- httpd関連プロセスのドメインのことである。
タイプ
ファイルに割り当てられるタイプの例を、以下に示す。
- file_t
- タイプが割り当てられていないことを示すタイプのこと。
- 制限されたドメインからはアクセス不可である。
- default_t
- 割り当てるべきタイプが設定されていない場合に、デフォルトで割り当てられるタイプのこと。
- 制限されたドメインからはアクセス不可である。
各ソフトウェアのポリシー設定
SELinuxを有効にしている場合、サービスが起動しない問題は、SELinuxポリシーによる制限が原因となる場合がある。
SELinuxはセキュリティ上の観点から、プログラムが実行できるアクションを制限することがある。
まず、ポリシーファイルを作成するために必要なライブラリをインストールする。
# RHEL sudo dnf install checkpolicy policycoreutils-python # SUSE sudo zypper install checkpolicy python3-policycoreutils policycoreutils-devel selinux-tools selinux-policy-devel # その他SELinux関連のツールもインストールする場合
SELinuxのログを確認する。
SELinuxがサービスをブロックしている場合、SELinuxのログにその旨のエラーメッセージが表示される。
まず、SELinuxログを確認する。
sudo tail -f /var/log/audit/audit.log
次に、ポリシーモジュール(TEファイル : Type Enforcement)とポリシーパッケージファイル (PPファイル : Policy Package) ファイルを作成する。
TEファイルとは、特定のドメインに対する全てのタイプとルールを定義するものである。
sudo grep <サービス名> /var/log/audit/audit.log | audit2allow -M <任意のポリシーファイル名>
必要であれば、TEファイルをコンパイルして、ポリシーモジュールファイル(.mod拡張子)を生成する。
checkmodule -M -m -o <任意のポリシーモジュール名>.mod <任意のポリシーモジュール名>.te
または、TEファイルから直接ポリシーパッケージファイル(.pp拡張子)を生成することもできる。
make -f /usr/share/selinux/devel/Makefile
もし、上記でTEファイルからポリシーモジュールファイル(.mod拡張子)を生成した場合、ポリシーパッケージ(.pp拡張子)を生成する。
semodule_package -o <任意のポリシーパッケージ名>.pp -m <任意のポリシーモジュール名>.mod
作成したポリシーモジュールをSELinuxにロードして、ポリシーを有効にする。
sudo semodule -i <任意のポリシーパッケージ名>.pp
ポリシーモジュールの有効化 / 無効化 / 削除
追加したポリシーは、有効化 / 無効化 / 削除することができる。
# ポリシーの有効化 sudo semodule -e <任意のポリシー名> # ポリシーの無効化 sudo semodule -d <任意のポリシー名> # ポリシーの削除 sudo semodule -r <任意のポリシー名>
ポリシーモジュールファイル (TEファイル) のシンタックス
ポリシーモジュールファイル (TEファイル) を作成することにより、特定のソフトウェアやサービスに対するカスタムポリシーを作成できる。
以下のセクションに示す要素を組み合わせて、特定のアプリケーションやサービスに対するSELinuxポリシーモジュールを作成することができる。
モジュール宣言
ポリシーパッケージの名前とバージョンを定義する。
これは、TEファイルの最初に記述する必要がある。
- モジュール名
- ポリシーパッケージの名前
- バージョン
- ポリシーの更新管理に使用される。
policy_module(<モジュール名>, <バージョン>) # または module <モジュール名> <バージョン>; 例: policy_module(myapp, 1.0)
タイプ定義
セキュリティコンテキストの一部となるタイプを定義する。
- タイプ
- SELinuxのセキュリティコンテキストの一部である。
- 一般的に、プロセス用のタイプ (_t)、実行ファイル用のタイプ (_exec_t)、データ用のタイプ (_data_t) 等を定義する。
- タイプ名は、アンダースコアで区切られた意味のある名前にすること。
type <タイプ名>; 例: type myapp_t; type myapp_exec_t; type myapp_data_t;
ドメイン遷移ルール
プロセスのドメイン変更を自動化する。
このルールにより、特定のタイプの実行ファイルが実行された時に、プロセスのドメインが自動的に変更される。
以下の例では、unconfined_tドメインのプロセスがmyapp_exec_tタイプの実行ファイルを実行する時、新しいプロセスはmyapp_tドメインで動作する。
domain_auto_trans(<ソースドメイン>, <実行ファイルタイプ>, <ターゲットドメイン>) 例: domain_auto_trans(unconfined_t, myapp_exec_t, myapp_t)
allowルール
基本的なアクセス制御を定義する。
ソースタイプ (通常はプロセス) がターゲットタイプ (ファイルやディレクトリ等) に対して特定の操作を行うことを許可する。
- クラス
- ファイル、ディレクトリ、ソケット等のリソースタイプを指定する。
- パーミッション
- read、write、execute等の操作を指定する。
allow <ソースタイプ> <ターゲットタイプ>:<クラス> { <パーミッション> }; 例: allow myapp_t myapp_data_t:file { read write getattr };
インタフェース使用
再利用可能なポリシールールを活用する。
インタフェースは、再利用可能なポリシールールの集合である。
共通の操作 (例: 設定ファイルの読み取り、ログの書き込み) に対して定義されている。
これにより、ポリシーの記述が簡潔になり、一貫性が保たれる。
インタフェース名(<タイプ1>, <タイプ2>, ...) 例: files_read_etc_files(myapp_t)
属性の定義と割り当て
複数のタイプをグループ化する。
- 属性名
- 複数のタイプをグループ化するために使用される。
- これにより、複数のタイプに対して1度にルールを適用できる。
- 例えば、全てのネットワークデーモンに共通のルールを適用する場合等に便利である。
attribute <属性名>; typeattribute <タイプ名> <属性名>; 例: attribute myapp_domain; typeattribute myapp_t myapp_domain;
ブール値の定義
ランタイムでのポリシー調整を可能にする。
ブール値は、ランタイムでポリシーの動作を変更するために使用される。
管理者は、setsebool
コマンドを使用してこれらの値を変更できる。
これにより、システムの再起動やポリシーの再コンパイル無しでポリシーを調整できる。
bool <ブール名> default <初期値>; 例: bool myapp_enable_feature default false;
条件付きポリシー
動的なポリシー適用を実現する。
条件付きポリシーは、ブール値の状態に基づいてポリシールールを動的に適用または除外する。
これにより、単一のポリシーモジュール内で異なる設定をサポートすることができる。
if (<条件>) { // ポリシールール } else { // 別のポリシールール } 例: if (myapp_enable_feature) { allow myapp_t user_home_t:file { read write }; }
ロールの割り当て
ユーザのアクセス可能なドメインを制限する。
- ロール
- ユーザがアクセスできるドメイン (タイプ) を制限するために使用される。
- 特定のロールにタイプを関連付けることにより、そのロールを持つユーザのみがそのタイプのプロセスを実行できる。
role <ロール名> types <タイプ名>; 例: role system_r types myapp_t;
ファイルコンテキストの指定
ファイルシステムのラベリングルールを定義する。
これは、指定されたタイプをファイルタイプとして宣言する。
ファイルタイプには、ファイルシステム関連の共通属性が自動的に割り当てられる。
これにより、ファイルシステムのラベリングルールを簡単に定義できる。
files_type(<タイプ名>) 例: files_type(myapp_data_t)