強制アクセス制御(SELinux)の基礎

2018年2月23日(金)
飯島 正人

はじめに

最近の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)にレベル別のアクセス制御を追加した機能です。ユーザやプロセスがアクセス可能な範囲を詳細に制御でき、非常に高度なセキュリティを実現できます。ただし、運用や管理が大変で、強固なセキュリティを求められる国防/軍事システムなどで利用されるような機能と言えます。こちらも企業ユーザで個別に設定して利用することはあまりないため、詳細は割愛します。

次回は、プロセスが乗っ取られた際に影響のある範囲をコマンドとツールを利用して調査する方法について解説します。

株式会社 日立製作所
日立製作所入社後、社内システムの開発、金融系SEを経て、現在はOSSソリューションセンタに所属し、セキュリティ分野のOSSを活用したソリューション開発に従事している。

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています