SELinux

SELinux(Security-Enhanced Linux)とは、セキュリティ関連のLinuxカーネル制御機能である。

SELinuxのせいでうまく動かなかったりして、SELinuxを無効にしてしまっている人は多いと思う。しかし、セキュリティに関わることなので、SELinuxについてしっかり理解して、有効状態で使えるようにしよう。

関連パッケージのインストール

CentOS 8には、SELinuxがデフォルトで入っているが、その他の関連パッケージをインストールしておく。

dnf install policycoreutils-python-utils setools-console selinux-policy-devel

動作モード

動作モードは、Enforcing、Permissive、Disabledの3つある。デフォルトはEnforcingである。

Enforcing
SELinuxが有効化され、アクセス制御が行われている。
Permissive
SELinuxが有効化されているが、アクセス制御は行わない。ポリシーに違反するアクセスは監査ログに記録される。
Disabled
SELinuxは無効化されており、アクセス制御や監査ログへの記録が行われない。

動作モードの確認

動作モードの確認は、getenforceコマンドで行う。

getenforce
Enforcing

getenforceコマンドは、いずれかの動作モードを返す。デフォルトはEnforcingである。

より詳しい状態の確認は、sestatusコマンドで行う。

sestatus
SELinux status:                 enabled
SELinuxfs mount:                /sys/fs/selinux
SELinux root directory:         /etc/selinux
Loaded policy name:             targeted
Current mode:                   enforcing
Mode from config file:          enforcing
Policy MLS status:              enabled
Policy deny_unknown status:     allowed
Memory protection checking:     actual (secure)
Max kernel policy version:      31

動作モードの変更

一時的な有効化と無効化は、setenforceコマンドで行う。

Permissiveへの一時切り替え

setenforce 0

Enforcingへの一時切り替え

setenforce 1

動作モードの恒久的変更

動作モードを恒久的に変更するためには、設定ファイルを編集する。

vi /etc/sysconfig/selinux

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.#     disabled - No SELinux policy is loaded.
SELINUX=enforcing

SELINUX=の後に動作モードを記述する。
設定ファイルを変更したら、設定を反映するためには、OSを再起動する必要がある。

Type Enforcement (TE)

SELinuxの動作モードがEnforcingになっている場合、プロセスからファイル、ディレクトリ、ソケットなど(まとめてリソースという。種類一つ一つをクラスという)にアクセスできるのは、許可されている場合のみに制限される。この仕組みをType Enforcementという。Linuxには、chmodで設定するパーミッションがあるが、アクセスが許可されるには、そのパーミッションによるアクセス制御に加えて、TEによるアクセス制御も通過しなければならない。

TEによるアクセス制御は、rootユーザにも適用される。あるプロセスの脆弱性を突かれ、rootユーザへ権限昇格されたとしても、そのプロセスのドメインに許可されていないリソースへのアクセスを防ぐ、というのがTEの狙いである。つまり、サーバに侵入されたとしても、その被害を最小限に抑えるための仕組みである。

ドメインとタイプ

全てのプロセスとリソースには、SELinuxコンテキストと呼ばれるものでラベル付けされている。

psコマンドに-Zオプションを付ければ、プロセスのSELinuxコンテキストを見ることができる。

ps -eZ
LABEL                             PID TTY          TIME CMD
system_u:system_r:init_t:s0         1 ?        00:00:02 systemd
system_u:system_r:kernel_t:s0       2 ?        00:00:00 kthreadd
system_u:system_r:kernel_t:s0       3 ?        00:00:00 rcu_gp
(略)

lsコマンドに-Zオプションを付ければ、ファイルなどのSELinuxコンテキストを見ることができる。

ls -lZ /tmp
合計 0
drwxr-xr-x. 2 root   root   system_u:object_r:user_tmp_t:s0  6  3月 19 07:08 hsperfdata_root
drwxr-x---. 2 tomcat tomcat system_u:object_r:tmp_t:s0      18  3月 21 00:14 hsperfdata_tomcat
(略)

system_u:system_r:init_t:s0のようになっている部分がSELinuxコンテキストである。書式は以下の通りである。

[SELinux User]:[Role]:[Type]:[Level]
SELinux User
SELinuxユーザの属性 SELinuxポリシーによりLinuxユーザはSELinuxユーザにマッピングされる。
Role
RBAC ( Role Based Access Control )の属性 SELinuxユーザのロールを定義する。 SELinuxポリシーにより、定義されたロールがどのドメインへアクセスできるかが制御される。
Type
TE (Type Enforcement) の属性 プロセスに対してはドメインを定義し、ファイルに対してはタイプを定義する。 定義されたドメインからタイプへのアクセス制御設定を基にアクセス可否が決定される。
Level
MLS (Multi Level Security) および MCS (Multi Category Security) の属性 レベルは [秘密度]:[カテゴリー] のペアで構成される。

TEによるアクセス制御

TEはホワイトリスト方式であり、ルールが定義されていない全てのアクセスは許可されず、監査ログに記録される。

ルールの設定は、「どのドメインが、どのタイプの、どのクラスに、どの操作を」という単位ごとに次の3種類の指定を行うことができる。

allow
アクセスを許可し、監査ログには記録しない
auditallow
アクセスを許可し、監査ログに記録する
dontaudit
アクセスを許可せず、監査ログに記録しない

つまり、未定義も含め、アクセスの許可・不許可と監査ログへの記録・不記録で4通り設定できる。

監査ログの確認

監査ログは、auditdサービスにより、デフォルトでは/var/log/audit/audit.logに出力される。

type=AVC msg=audit(1584722139.563:90): avc:  denied  { name_connect } for  pid=2366 comm="php-fpm" dest=80 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:http_port_t:s0 tclass=tcp_socket permissive=0
type=SYSCALL msg=audit(1584722139.563:90): arch=c000003e syscall=42 success=no exit=-13 a0=9 a1=7ffc1700e480 a2=10 a3=28fac4c383045d items=0 ppid=938 pid=2366 auid=4294967295 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) ses=4294967295 comm="php-fpm" exe="/usr/sbin/php-fpm" subj=system_u:system_r:httpd_t:s0 key=(null)ARCH=x86_64 SYSCALL=connect AUID="unset" UID="apache" GID="apache" EUID="apache" SUID="apache" FSUID="apache" EGID="apache" SGID="apache" FSGID="apache"

監査ログは、以下のコマンドで見ることもできる。

type=AVC msg=audit(1584722139.563:90): avc:  denied  { name_connect } for  pid=2366 comm="php-fpm" dest=80 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:http_port_t:s0 tclass=tcp_socket permissive=0
type=SYSCALL msg=audit(1584722139.563:90): arch=c000003e syscall=42 success=no exit=-13 a0=9 a1=7ffc1700e480 a2=10 a3=28fac4c383045d items=0 ppid=938 pid=2366 auid=4294967295 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) ses=4294967295 comm="php-fpm" exe="/usr/sbin/php-fpm" subj=system_u:system_r:httpd_t:s0 key=(null)ARCH=x86_64 SYSCALL=connect AUID="unset" UID="apache" GID="apache" EUID="apache" SUID="apache" FSUID="apache" EGID="apache" SGID="apache" FSGID="apache"

一時的なコンテキストの変更

一時的にそのファイルに対してコンテキストを変更する。-Rオプションを付ければ、再起的に配下のディレクトリ、ファイルも全て変更される。

chcon -t [type] [file_path]

コンテキストの復元

リソースのコンテキストをデフォルトの設定に戻すには、以下のコマンドを実行する。

restorecon [file]

-Rオプションを付ければ、再起的に配下のディレクトリ、ファイルも全てデフォルトのコンテキストに復元される。

ブール値によるアクセス制御

ブール値によるアクセス制御の状態は、getseboolで行える。

getsebool httpd_can_network_connect_db
httpd_can_network_connect_db --> on

全ての設定状態を確認するには、-aオプションを指定する。

getsebool -a
abrt_anon_write --> off
abrt_handle_event --> off
abrt_upload_watch_anon_write --> on
antivirus_can_scan_system --> on
antivirus_use_jit --> on
・・・

setseboolコマンドを使用して、設定を変更することができる。

setsebool -P httpd_can_network_connect_db on

-Pオプションを付けると、再起動後も設定が有効のままになる。

%d人のブロガーが「いいね」をつけました。