強制アクセス制御(SELinux)の基礎
はじめに
最近のLinuxには、強制アクセス制御(MAC:Mandatory Access Control)と呼ばれるセキュリティを強化する機能が標準で搭載されています。この強制アクセス制御機能を活用することで、サーバに不正侵入を許した場合でも被害を限定化するなどリスクを低減することができます。
強制アクセス制御の実装としては、SELinux(Security-Enhanced Linux)やAppArmor(Application Armor)、TOMOYO Linuxなどいくつかの種類がありますが、ここではRed Hat Enterprise LinuxやFedoraといった主要ディストリビューションに標準実装されているSELinuxについて紹介します。
SELinuxの概要
SELinuxとは、アメリカ国家安全保障局(NSA)が中心となって開発した、Linuxのカーネルに強制アクセス制御を付加するモジュールです。Red Hat Enterprise Linux、CentOS、Fedoraのカーネルに標準で組み込まれています。
強制アクセス制御は、「誰が何にどのようにアクセスできるか」というセキュリティポリシーに従ったアクセス制御を強制します。このアクセス制御はホワイトリスト形式となっており、あらかじめ定義したアクセスルール以外のアクセスについてはすべて拒否します。
例えば、あるプログラムが脆弱性を突かれ、プロセスを乗っ取られてroot権限に昇格された場合、従来からある任意アクセス制御(DAC:Discretionary Access Control)ではroot特権によりすべてのファイルにアクセスが可能で、システム全体に影響が及んでしまいます。対してSELinuxが有効なシステムでは、強制アクセス制御(MAC)によりそのプロセスがアクセスできる範囲を限定します。結果、破壊活動を行おうとしてもアクセス拒否が発生し、動きを封じ込めることができます。
この仕組みにより、SELinuxは定期的なパッチの適用が難しいシステムや、一般に知られない間に脆弱性が発生する「ゼロディ攻撃」などに有効であると言われています。
ただし、SELinuxはサーバに侵入された後の被害を極小化させるものであり、侵入を防ぐものではありませんので、ファイアウォールや侵入検知システムなど侵入させないための仕組みが必要です。
それでは、従来から利用されているDAC(任意アクセス制御)とMAC(強制アクセス制御)の違いについて見ていきましょう。
DAC(任意アクセス制御)は、ログインユーザ情報とリソースの所有者情報を基にアクセス制御を行うものです。また、ファイルの所有者がパーミッションの設定を自由に変更できるほか、rootユーザは特権によりすべてのファイルにアクセスすることが可能です。
一方のMAC(強制アクセス制御)は、セキュリティポリシーに従ったアクセス制限をrootユーザを含む全てのユーザやプロセスに強制させる仕組みです。セキュリティポリシーに登録されているアクセスルールはセキュリティ管理者のみが変更でき、ファイルの所有者でもアクセスルールを変更できないようになっています。
この2つのアクセス制御の違いを簡単にまとめると、以下のようになります。
項目 | 従来のアクセス制御 DAC(任意アクセス制御) |
SELinuxでのアクセス制御 MAC(強制アクセス制御) |
---|---|---|
アクセス制御方式 | 伝統的なUNIXパーミッションによるアクセス制御 | セキュリティポリシーによる強制アクセス制御 |
制御内容 | ユーザIDやグループID とリソースの所有者・所有グループ情報を基にアクセスの正当性を判断する | アクセスルールをセキュリティポリシーとして集中管理しており、システムレベルでアクセス制御を強制的に執行する |
アクセス権の変更 | ファイルの所有者がファイルのパーミッションを自由に設定・変更することが可能 | ファイルの所有者であってもアクセスルールの変更は不可 |
セキュリティ | root特権を奪うと何でもできる | プロセスに制限が掛かるため、root特権を奪われても影響範囲が限定される |
強制アクセス制御には様々なモデルが存在します。例えば「誰が」の識別方法1つをとっても、プロセス毎の権限名で識別したり、ユーザの組織での役割名で識別したりします。
SELinuxは以下のような複数の強制アクセス制御のモデルをサポートし、用途に応じてこれらを適切に構成することで、システムの各要素に最小限の権限を持たせ、結果として攻撃された場合の被害を最小化することができます。
アクセス制御モデル | 主な用途 |
---|---|
TE(Type Enforcement) | プロセス毎の権限の最小化 |
RBAC(Role Based Access Control) | ログインユーザの権限の最小化 |
MCS(Mucti Category Security) | コンテナ毎の権限の分離 |
MLS(Multi Level Security) | 軍用のアクセス制御 |
以降では、SELinuxの強制アクセス制御を構成するそれぞれのアクセス制御モデルについて見ていきます。
TE(Type Enforcement)
TEは、SELinuxの強制アクセス制御として最も主要なものです。プロセスがリソースにアクセスする権限を制御する機能で、定義したアクセスルールはセキュリティポリシー・ファイルに保存されています。
SELinuxを導入したシステムでは、セキュリティコンテキストと呼ばれるラベルがシステム上の全てのプロセスやリソースに割り当てられます。ラベルには主にプロセスに割り当てられるドメインとリソースに割り当てられるタイプがあり、このドメインからタイプにアクセス権を定義してアクセス制御を行う仕組みになっています。
RBAC(Role Based Access Control)
RBACは、システム管理者やWeb管理者、DB管理者のような、ロールと呼ばれる役割に応じたアクセス権をユーザに付与することでアクセス制御を行う機能です。ログインユーザに対しても操作可能な範囲を制限することができます。
RBACには、デフォルトで以下のような運用管理向けのロールが準備されています。
役割 | ロール名 | 説明 |
---|---|---|
Web管理 | webadm_r | Apache HTTPサーバに関連するSELinuxタイプの管理が可能 |
DB管理 | dbadm_r | MariaDBデータベースおよびPostgreSQLデータベース管理システムに関連するSELinuxタイプの管理が可能 |
ログ管理 | logadm_r | syslogおよびauditlogプロセスに関連するSELinuxタイプの管理が可能 |
SELinux管理 | secadm_r | SELinuxの管理が可能 |
監査システム管理 | auditadm_r | auditサブシステムに関連するプロセスの管理が可能 |
これらのロールを上手く利用すると、例えばrootユーザに制限をかけることも可能になります。デフォルトで準備されているロールが実際の運用体制に合わない場合は、必要に応じて独自のロールを作成することもできます。
RBACについては本稿の執筆時点であまり文献が出回っていないため、ここでRBACの仕組みを詳しく解説します。
OSにログインするLinuxユーザにSELinuxの制限を掛けるため、LinuxユーザはSELinuxポリシーによりSELinuxユーザ、ロール、ドメインにマッピングされます。
rootユーザでログインしてid -Zコマンドを実行すると、以下のように表示されます。
この場合、rootユーザはSELinuxユーザ:unconfined_u、ロール:unconfined_r、ドメイン:unconfined_tにマッピングされています。このマッピングされたドメインをサブジェクト(動作主体)として、TEによりアクセス制御が行われます。
Linuxユーザにマッピング可能なSELinuxユーザと、それぞれの権限は以下のとおりです。
SELinuxユーザ | X Windowログイン | suまたはsudoの実行 | $HOMEおよび/tmpでの アプリケーション実行 |
ネットワークへのアクセス |
---|---|---|---|---|
sysadm_u | 可 | su、sudo | 可 | 可 |
staff_u | 可 | sudoのみ | 可 | 可 |
user_u | 可 | 不可 | 可 | 可 |
guest_u | 不可 | 不可 | 不可 | 不可 |
xguest_u | 可 | 不可 | 不可 | Firefoxのみ | unconfined_u | 制限なし | 制限なし | 制限なし | 制限なし |
現在rootユーザにマッピングされている unconfined_u は、全項目で制限を受けないユーザだとわかります。また、実際のアクセス制御に使用されるドメインも unconfined_t となっており、ほぼ制限を受けません。
つまり、telnetやsshなどでコンソールログインすると、rootユーザは何でもできる状態になっています。rootユーザは攻撃者に狙われやすいため、何らかの制限を掛けることが望ましいです。
今回はrootユーザのsuやsudo権限にも制限を掛けるため、rootユーザにマッピングするSELinuxユーザはuser_uを使用します。ロールとドメインはuser_uに紐づく一般ユーザ権限のuser_rロール、user_tドメインを使用します。イメージとしては、下図のようになります。
設定手順
それでは、rootユーザの権限を制限してみましょう。まず、SELinuxユーザマッピング設定を変更するために、現在の設定を確認します。
# semanage login -l
ログイン名 SELinux ユーザ MLS/MCS 範囲 サービス
root unconfined_u s0-s0:c0.c1023 *
rootユーザのマッピング設定はunconfined_uです。これをuser_uに変更します。
# semanage login -a -s user_u root
変更後、SELinuxユーザマッピング設定がuser_uに変更されていることを確認します。
# semanage login -l
ログイン名 SELinux ユーザ MLS/MCS 範囲 サービス
root user_u s0 *
次に、SELinuxユーザとロールのマッピング設定を確認します。
# semanage user –l
user_u user s0 s0-s0:c0.c1023 user_r
こちらは、デフォルトでuser_rロールにマッピング設定されているので変更不要です。
続いて、ログイン時に必要な読み取り権限と実行権限を付与します。まず、ポリシーを追加するためのアクセスルール定義ファイル(teファイル)を作成します。
- 作業用ディレクトリ:/tmp/work
- ポリシー名:Login_user
- ファイル名:/tmp/work /Login_user.te
以下の内容のファイルを作成します。
module Login_user 1.0;
require {
type user_t;
type admin_home_t;
class file { ioctl read getattr execute execute_no_trans append open write };
class capability { dac_override dac_read_search };
}
allow user_t admin_home_t:file { ioctl read getattr execute execute_no_trans append open write };
allow user_t self:capability { dac_override dac_read_search };
次にポリシーモジュールを登録します。
# cd /tmp/work
# make -f /usr/share/selinux/devel/Makefile
# semodule -i /tmp/work/Login_user.pp
これで設定の変更は完了です。rootユーザでログインすると、以下のように一般ユーザ権限に変更されています。
# id –Z
user_u:user_r:user_t:s0
また、通常運用時はrootユーザを一般ユーザ化しますが、システムメンテナンスなどの場面ではシステム管理者権限が必要になることがあります。このままではrootユーザはsuもsudoも使用できないため、SELinux管理者でログインし、rootユーザのマッピング設定を変更することで対応します。
今回は、rootユーザにマッピングしているSELinuxユーザをstaff_uに変更し、rootユーザでログイン後にロールを変更してみます。
イメージとしては、下図のようになります。
設定手順
まず、SELinuxユーザマッピング設定をstaff_uに変更するため、現在のSELinuxユーザマッピング設定を確認します。
# semanage login -l
ログイン名 SELinux ユーザ MLS/MCS 範囲 サービス
root user_u s0-s0:c0.c1023 *
rootユーザのマッピング設定をstaff_uに変更します。
# semanage login -m -S targeted -s staff_u -r s0-s0:c0-c1023 root
変更後、SELinuxユーザマッピング設定がstaff_uに変更されていることを確認します。
# semanage login -l
ログイン名 SELinux ユーザ MLS/MCS 範囲 サービス
root staff_u s0-s0:c0-c1023 *
最後に、SELinuxユーザとロールのマッピング設定を確認してみましょう。
# semanage user -l
staff_u user s0 s0-s0:c0.c1023 staff_r sysadm_r system_r unconfined_r
これはstaff_uがstaff_r、sysadm_r、system_r、unconfined_rのロールを利用できるという設定です。今回必要な権限はsysadm_rなので設定を変更しなくても問題はありませんが、他のユーザでstaff_uをマッピングする用途がある場合は、制限がないunconfined_rを削除しておいた方が良いでしょう。
unconfined_rのロールを削除するには、以下のコマンドを実行します。
# semanage user -m -R "staff_r sysadm_r system_r" staff_u
変更後のSELinuxユーザとロールのマッピング設定を確認するとunconfined_rが削除されています。
# semanage user -l
staff_u user s0 s0-s0:c0.c1023 staff_r sysadm_r system_r
続いて、ログイン時に必要な読み取り権限と実行権限を付与します。ポリシーを追加するためのアクセスルール定義ファイル(teファイル)を作成します。
- 作業用ディレクトリ:/tmp/work
- ポリシー名:Login_staff
- ファイル名:/tmp/work /Login_staff.te
まず、以下の内容のファイルを作成します。
module Login_staff 1.0;
require {
type staff_t;
type admin_home_t;
class file { ioctl read getattr execute execute_no_trans append open write };
class capability { dac_override dac_read_search };
}
allow staff_t admin_home_t:file { ioctl read getattr execute execute_no_trans append open write };
allow staff_t self:capability { dac_override dac_read_search };
次に、ポリシーモジュールを登録します。
# cd /tmp/work
# make -f /usr/share/selinux/devel/Makefile
# semodule -i /tmp/work/Login_staff.pp
これで、設定の変更は完了です。rootユーザでログインすると、以下のように変更されました。
# id –Z
staff_u:staff_r:staff_t:s0-s0:c0
SELinuxユーザがstaff_uになったので、システム管理者ロールに切り替えることができます。
では、権限昇格してみましょう。
# newrole -r sysadm_r
※newroleコマンドを利用するには、policycoreutils-newroleパッケージが必要
id –Zコマンドで確認すると、ロールとドメインがシステム管理者のものに変更されました。これで、システムメンテナンス作業が可能になります。
# id –Z
staff_u:sysadm_r:sysadm_t:s0-s0:c0
なお、メンテナンス作業終了後は、速やかにマッピング設定を戻すことを忘れないようにしてください。
また、今回の解説内容でrootユーザを一般ユーザ権限に変更することが可能ですが、動作を保証するものではありません。実際にシステムに適用する場合は、運用を考慮したユーザやロール、付与する権限について設計、テストを実施したうえで適用してください。
例えば、今回はRBACについて簡単に解説するためユーザ名rootで直接ログインさせています。実運用時はsudoで一般ユーザを作成し、そのユーザにロールを付与するほうが望ましいです。
MCS(Multi Category Security)
MCSはユーザやリソースなどにカテゴリというラベルを付与することで、カテゴリ別のアクセス制御を行うものです。ユーザがファイルなどのリソースにアクセスする際に部署ごとにアクセス制限を掛けるといったことに利用できます。
しかし、現在はDockerやOpenShiftなどコンテナ間のセキュリティを保つために利用されるケースが主流です。企業ユーザで個別に設定して利用することはあまりないため、詳細は割愛します。
MLS(Multi Level Security)
MLSは、カテゴリ別のアクセス制御(MCS)にレベル別のアクセス制御を追加した機能です。ユーザやプロセスがアクセス可能な範囲を詳細に制御でき、非常に高度なセキュリティを実現できます。ただし、運用や管理が大変で、強固なセキュリティを求められる国防/軍事システムなどで利用されるような機能と言えます。こちらも企業ユーザで個別に設定して利用することはあまりないため、詳細は割愛します。
次回は、プロセスが乗っ取られた際に影響のある範囲をコマンドとツールを利用して調査する方法について解説します。
連載バックナンバー
Think ITメルマガ会員登録受付中
全文検索エンジンによるおすすめ記事
- ownCloud導入はじめの一歩(仮想マシンイメージとCentOS 7のインストール手順)
- DBセキュリティの第2弾、アクセス・コントロールと権限管理
- Red Hat Enterprise Linuxセキュリティの概要と特徴
- セキュアOS紹介(2) 〜 Trusted SolarisとPitBull
- OSSのセキュリティや開発ツール、実行基盤などの最前線の最新情報・動向が得られる ―「DevConf.cz 2020」レポート
- MIRACLE LINUXのセキュリティへの取り組み
- Oracle Cloud Hangout Cafe Season4 #4「マイクロサービスの認証・認可とJWT」(2021年7月7日開催)
- Linuxの認証を簡単にする「FreeIPA」とは
- WWWサーバーのネットワーク設定
- Lab Managerの運用と管理