LoginSignup
19
23

More than 3 years have passed since last update.

SELinux

Last updated at Posted at 2017-03-14

1 環境

CentOS版数
[root@master ~]# cat /etc/redhat-release
CentOS Linux release 7.3.1611 (Core)
カーネル版数
[root@master ~]# uname -r
3.10.0-514.el7.x86_64

2 SELinuxで使うコマンドとパッケージ

コマンド パッケージ名 備考
semanage policycoreutils-python ファイルやポートに対するタイプを変更する
audit2allow 同上 ログからルールを作成する
audit2why 同上 ログからアクセス拒否の理由を出力する
restorecon policycoreutils デフォルトの SELinux コンテキストを復元する
semodule 同上 モジュールのインストール、削除等をおこなう
sestatus 同上 SElinuxの状態やBoolean値の状態を表示する
sesearch setools-console
seinfo 同上
findcon 同上 ファイルコンテキストを探す
sepolicy policycoreutils-devel
chcon coreutils
matchpathcon libselinux-utils
setroubleshootd setroubleshoot-server

3 セキュリティコンテキストの変更方法

ここでは、セキュリティコンテキストのタイプの変更方法について説明する。

3.1 一時的に変更する方法(chcon)

restoreconを実行すると、タイプがデフォルトのタイプに戻る。

テスト用のファイル(index.html)を作成する。
[root@master ~]# touch /var/www/html/index.html

テスト用ファイルのセキュリティコンテキストを確認する。タイプはhttpd_sys_content_tであることがわかる。
[root@master ~]# ls -lZ /var/www/html/index.html
-rw-r--r--. root root unconfined_u:object_r:★httpd_sys_content_t:s0 /var/www/html/index.html

タイプをsamba_share_tに変更する。
[root@master ~]# chcon -t samba_share_t /var/www/html/index.html

タイプを確認する。samba_share_tに変更されたことがわかる。
[root@master ~]# ls -lZ /var/www/html/index.html
-rw-r--r--. root root unconfined_u:object_r:★samba_share_t:s0 /var/www/html/index.html

リブートする。
[root@master ~]# shutdown -r now

タイプを確認する。リブート前のタイプ(samba_share_t)と同じであることがわかる。
つまり、リブートしてもタイプは変更されない、ということ。
[root@master ~]# ls -lZ /var/www/html/index.html
-rw-r--r--. root root unconfined_u:object_r:samba_share_t:s0 /var/www/html/index.html

restoreconを実行する。
[root@master ~]# restorecon /var/www/html/index.html

タイプがhttpd_sys_content_tに戻ったことがわかる(★印)
[root@master ~]# ls -lZ /var/www/html/index.html
-rw-r--r--. root root unconfined_u:object_r:★httpd_sys_content_t:s0 /var/www/html/index.html

3.2 永続的に変更する方法(semanage)

セキュリティコンテキストの変更
セキュリティコンテキストのタイプを確認する。httpd_sys_content_tであることがわかる(★印)。
[root@master ~]# ls -lZ /var/www/html/index.html
-rw-r--r--. root root unconfined_u:object_r:★httpd_sys_content_t:s0 /var/www/html/index.html

タイプをsamba_share_t に変更する(★印)
[root@master ~]# semanage fcontext -a -t ★samba_share_t /var/www/html/index.html

semanageを実行すると、セキュリティコンテキストがファイル(file_contexts.local)に保存されることがわかる。
[root@master ~]# grep index.html /etc/selinux/targeted/contexts/files/file_contexts.local
/var/www/html/index.html    system_u:object_r:samba_share_t:s0

タイプを確認する。タイプは変更されていないことがわかる。
[root@master ~]# ls -lZ /var/www/html/index.html
-rw-r--r--. root root unconfined_u:object_r:★httpd_sys_content_t:s0 /var/www/html/index.html

restoreconを実行する。
[root@master ~]# restorecon /var/www/html/index.html

タイプを確認する。samba_share_tに変更されたことがわかる(★印)。
[root@master ~]# ls -lZ /var/www/html/index.html
-rw-r--r--. root root unconfined_u:object_r:★samba_share_t:s0 /var/www/html/index.html
[root@master ~]#
デフォルトのセキュリティコンテキストに変更
セキュリティコンテキストのタイプを確認する。タイプはsamba_share_tであることがわかる。
[root@master ~]# ls -lZ /var/www/html/index.html
-rw-r--r--. root root unconfined_u:object_r:★samba_share_t:s0 /var/www/html/index.html

タイプからsamba_share_t を削除する。
[root@master ~]# semanage fcontext -d -t samba_share_t /var/www/html/index.html

セキュリティコンテキストのタイプを確認する。
[root@master ~]# ls -lZ /var/www/html/index.html
-rw-r--r--. root root unconfined_u:object_r:★samba_share_t:s0 /var/www/html/index.html

[root@master ~]# grep index.html /etc/selinux/targeted/contexts/files/file_contexts.local

restoreconを実行する。
[root@master ~]# restorecon /var/www/html/index.html

タイプを確認する。タイプがhttpd_sys_content_tに戻ったことがわかる。
[root@master ~]# ls -lZ /var/www/html/index.html
-rw-r--r--. root root unconfined_u:object_r:★httpd_sys_content_t:s0 /var/www/html/index.html

4 アクセスエラーが発生した場合の対処方法

アクセスエラーが発生した場合、下記いずれかの方法でアクセスを許可することができる。
1は推奨しない。

  1. OS全体のSELinux無効化(setenfore 0または/etc/sysconfig/selinux)
  2. 特定ドメインのみアクセスを許可する。
  3. ルールを作成して、アクセスを許可する。

4.1 OS全体でSELinuxを無効化する方法

[root@master ~]# cat /var/www/html/index.html
test

[root@master ~]# ls -lZ /var/www/html/index.html
-rw-r--r--. root root unconfined_u:object_r:samba_share_t:s0 /var/www/html/index.html
[root@master ~]#

httpdプロセスのドメインを確認する。ドメインはhttpd_tであることがわかる。
[root@master ~]# ps -Z -C httpd
LABEL                              PID TTY          TIME CMD
system_u:system_r:httpd_t:s0      6683 ?        00:00:01 httpd
system_u:system_r:httpd_t:s0      6684 ?        00:00:00 httpd
system_u:system_r:httpd_t:s0      6685 ?        00:00:00 httpd
system_u:system_r:httpd_t:s0      6686 ?        00:00:00 httpd
system_u:system_r:httpd_t:s0      6687 ?        00:00:00 httpd
system_u:system_r:httpd_t:s0      6688 ?        00:00:00 httpd
[root@master ~]#

httpd_tドメインが httpd_sys_content_tタイプにアクセス可能かどうか確認する。
[root@master ~]# sesearch -A -s httpd_t -t httpd_sys_content_t
Found 25 semantic av rules:
   allow httpd_t httpd_sys_content_t : dir { ioctl read getattr lock search open } ;
   allow httpd_t httpd_sys_content_t : lnk_file { read getattr } ;
   allow daemon httpd_sys_content_t : dir { getattr search open } ;
   allow httpd_t httpd_content_type : file { ioctl read getattr lock open } ;
   allow httpd_t file_type : filesystem getattr ;
   allow httpd_t file_type : dir { getattr search open } ;
   allow httpd_t httpd_content_type : dir { getattr search open } ;
   allow httpd_t httpd_sys_content_t : file { ioctl read getattr lock open } ;
   allow httpd_t httpd_sys_content_t : dir { ioctl read write getattr lock add_name remove_name search open } ;
   allow httpd_t httpd_content_type : lnk_file { read getattr } ;
   allow httpd_t httpdcontent : file { ioctl read write create getattr setattr lock append unlink link rename open } ;
   allow httpd_t httpdcontent : file { read getattr execute open } ;
   allow httpd_t httpdcontent : dir { ioctl read write getattr lock add_name remove_name search open } ;
   allow httpd_t httpdcontent : dir { ioctl read write getattr lock add_name remove_name search open } ;
   allow httpd_t httpdcontent : dir { ioctl read write create getattr setattr lock unlink link rename add_name remove_name reparent search rmdir open } ;
   allow httpd_t httpdcontent : dir { ioctl read write getattr lock add_name remove_name search open } ;
   allow httpd_t httpdcontent : dir { ioctl read write getattr lock add_name remove_name search open } ;
   allow httpd_t httpdcontent : dir { ioctl read write getattr lock add_name remove_name search open } ;
   allow httpd_t httpdcontent : dir { ioctl read write getattr lock add_name remove_name search open } ;
   allow httpd_t httpd_content_type : file { ioctl read getattr lock open } ;
   allow httpd_t httpdcontent : lnk_file { ioctl read write create getattr setattr lock append unlink link rename } ;
   allow httpd_t httpd_content_type : dir { getattr search open } ;
   allow httpd_t httpd_content_type : dir { getattr search open } ;
   allow httpd_t httpd_content_type : dir { ioctl read getattr lock search open } ;
   allow httpd_t httpd_content_type : dir { getattr search open } ;

httpアクセスをする。アクセスが拒否されたことがわかる。
[root@master ~]# curl http://localhost/index.html
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
-以下、略-

OS全体のSELinuxを無効化する。
[root@master ~]# setenforce 0

SELinxuの状態を確認する。SELinux無効であることがわかる。
[root@master ~]# getenforce
Permissive

httpアクセスする。今度はアクセスできた。
[root@master ~]# curl http://localhost/index.html
test

4.2 特定ドメインだけSELinuxを無効化する方法

SELinuxの状態を確認する。OS全体でSELinuxが有効になっていることがわかる。
[root@master ~]# getenforce
Enforcing

http_dドメインのSELinuxを無効化する。
[root@master ~]# semanage permissive -a httpd_t

http_dドメインのSELinuxが無効化されたことがわかる。
[root@master ~]# semanage permissive -l|grep httpd_t
httpd_t

httpアクセスする。アクセスできることがわかる。
[root@master ~]# curl http://localhost/index.html
test

http_dドメインのSELinuxを有効化する。
[root@master ~]# semanage permissive -d httpd_t
libsemanage.semanage_direct_remove_key: Removing last permissive_httpd_t module (no other permissive_httpd_t module exists at another priority).

http_dドメインのSELinuxが有効化されたことがわかる(リスト表示されないので)
[root@master ~]# semanage permissive -l|grep httpd_t

httpアクセスする。アクセスが拒否されたことがわかる。
[root@master ~]# curl http://localhost/index.html
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access /index.html
on this server.</p>
</body></html>

4.3 ルールを作成する方法

[root@master selinux]# getenforce
Enforcing

[root@master selinux]# ls -lZ /var/www/html/index.html
-rw-r--r--. root root unconfined_u:object_r:samba_share_t:s0 /var/www/html/index.html

[root@master selinux]# curl http://localhost/index.html
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access /index.html
on this server.</p>
</body></html>

audit.logからアクセス許可のルールを作成する。
[root@master selinux]# audit2allow -M test < /var/log/audit/audit.log
******************** IMPORTANT ***********************
To make this policy package active, execute:

semodule -i test.pp

ファイルを確認する。
[root@master selinux]# ls
test.pp  test.te

ルールの中身を確認する。
[root@master selinux]# cat test.te

module test 1.0;

require {
        type httpd_t;
        type samba_share_t;
        class file { getattr open read };
}

#============= httpd_t ==============

#!!!! The file '/var/www/html/index.html' is mislabeled on your system.
#!!!! Fix with $ restorecon -R -v /var/www/html/index.html
allow httpd_t samba_share_t:file { getattr open read };
[root@master selinux]#

モジュール(test.pp)をインストールする。
[root@master selinux]# semodule -i test.pp

インストールされているモジュールを確認する。
[root@master selinux]# semodule -l|grep -w test
test    1.0

httpアクセスする。今度はアクセスできた。
[root@master selinux]# curl http://localhost/index.html
test

モジュールを削除する。
[root@master selinux]# semodule -r test
libsemanage.semanage_direct_remove_key: Removing last test module (no other test module exists at another priority).

インストールされているモジュールを確認する。モジュールが削除できたことがわかる。
[root@master selinux]# semodule -l|grep -w test
[root@master selinux]#

httpアクセスをする。モジュールを削除してルールがなくなったので、アクセス拒否されたことがわかる。
[root@master selinux]# curl http://localhost/index.html
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>

5 semanageコマンド

ディレクトリやポートに対するセキュリティコンテキストの設定、変更、削除を行う。

5.1 ディレクトリに対する操作

5.1.1 設定方法(-a)

テスト用ディレクトリを作成する。
[root@master ~]# mkdir -p /var/example

作成したディレクトリのセキュリティコンテキストのタイプを確認する。タイプがvar_tであることがわかる(★印)。
[root@master ~]# ls -lZd /var/example
drwxr-xr-x. root root unconfined_u:object_r:★var_t:s0   /var/example

/var/example配下のタイプをhttpd_sys_rw_content_tに設定する。"-a"が設定、"-t"がタイプを意味する。
[root@master ~]# semanage fcontext -a -t httpd_sys_rw_content_t "/var/example(/.*)?"

/var/example配下にhttpd_sys_rw_content_tのタイプが設定できたことがわかる。
[root@master ~]# semanage fcontext -l|grep /var/example
/var/example(/.*)?                                 all files          system_u:object_r:★httpd_sys_rw_content_t:s0

セキュリティコンテキストを確認する。テスト用ディレクトリのタイプは、var_tのままであることがわかる。
[root@master ~]# ls -lZd /var/example
drwxr-xr-x. root root unconfined_u:object_r:★var_t:s0   /var/example

restoreconを実行する。
[root@master ~]# restorecon -R /var/example

5.1.2 変更方法(-m)

セキュリティコンテキストを変更する。"-m"が変更、"-t"がタイプを意味する。
[root@master ~]# semanage fcontext -m -t public_content_t "/var/example(/.*)?"

セキュリティコンテキストのタイプを確認する。タイプは元のままであることがわかる(★印)。
[root@master ~]# ls -ldZ /var/example/
drwxr-xr-x. root root unconfined_u:object_r:★httpd_sys_rw_content_t:s0 /var/example/

restoreconを実行する。
[root@master ~]# restorecon -R /var/example/

ファイルコンテキストを確認する。指定したタイプが設定されていることがわかる(★印)。
[root@master ~]# ls -ldZ /var/example/
drwxr-xr-x. root root unconfined_u:object_r:★public_content_t:s0 /var/example/

5.1.3 削除方法(-d)

セキュリティコンテキストを削除する。"-a"が削除を意味する。
[root@master ~]# semanage fcontext -d "/var/example(/.*)?"

セキュリティコンテキストを確認する。タイプは元のままであることがわかる(★印)。
[root@master ~]# ls -ldZ /var/example/
drwxr-xr-x. root root unconfined_u:object_r:★public_content_t:s0 /var/example/

restoreconを実行する。
[root@master ~]# restorecon -R /var/example/

セキュリティコンテキストを確認する。デフォルトのタイプに戻ったことがわかる(★印)。
[root@master ~]# ls -ldZ /var/example/
drwxr-xr-x. root root unconfined_u:object_r:★var_t:s0   /var/example/

5.2 ポートに対する操作

ポートコンテキストにポート番号(22222)を追加する。"-a"が設定、"-t"がタイプを意味する。
[root@master ~]# semanage port -a -t kubernetes_port_t -p tcp 22222

ポートコンテキストを確認する。22222番ポートが登録されたことがわかる(★印)。
[root@master ~]# semanage port -l |grep kubernetes_port_t
kubernetes_port_t              tcp    ★22222, 4001, 4194, 10250

ポートコンテキストからポート番号(22222)を削除する。
[root@master ~]# semanage port -d -t kubernetes_port_t -p tcp 22222

ポートコンテキストを確認する。22222番ポートが削除されたことがわかる。
[root@master ~]# semanage port -l |grep kubernetes_port_t
kubernetes_port_t              tcp      4001, 4194, 10250
[root@master ~]#

docker,kuberneteのポートコンテキストを表示する。
8080はkube-apiserver、10250はkubelet,4001はetcdのポート番号。他は良くわからない。
[root@master ~]# semanage port -l |grep -e 8080 -e 10250
http_cache_port_t              tcp      8080, 8118, 8123, 10001-10010
kubernetes_port_t              tcp      4001, 4194, 10250
[root@master ~]#

6 アクセス制御ルールの調査方法(sesearch)

6.1 allowルールの調べ方

httpd_tドメインが、httpd_sys_content_tタイプにアクセス可能かどうかを調べる。
一番最初に表示された結果(●印)をみると、httpd_tドメインは、httpd_sys_content_tタイプの
ディレクトリ(dir)に対して、ioctl,..,openできることがわかる。
[root@master ~]# sesearch -A -n -s httpd_t -t httpd_sys_content_t
Found 25 semantic av rules:
  ●allow httpd_t httpd_sys_content_t : dir { ioctl read getattr lock search open } ;
   allow httpd_t httpd_sys_content_t : lnk_file { read getattr } ;
   allow daemon httpd_sys_content_t : dir { getattr search open } ;
   allow httpd_t httpd_content_type : file { ioctl read getattr lock open } ;
   allow httpd_t ★file_type : filesystem getattr ;
   allow httpd_t ★file_type : dir { getattr search open } ;
   allow httpd_t httpd_content_type : dir { getattr search open } ;
   allow httpd_t httpd_sys_content_t : file { ioctl read getattr lock open } ;
   allow httpd_t httpd_sys_content_t : dir { ioctl read write getattr lock add_name remove_name search open } ;
   allow httpd_t httpd_content_type : lnk_file { read getattr } ;
   allow httpd_t httpdcontent : file { ioctl read write create getattr setattr lock append unlink link rename open } ;
   allow httpd_t httpdcontent : file { read getattr execute open } ;
   allow httpd_t httpdcontent : dir { ioctl read write getattr lock add_name remove_name search open } ;
   allow httpd_t httpdcontent : dir { ioctl read write getattr lock add_name remove_name search open } ;
   allow httpd_t httpdcontent : dir { ioctl read write create getattr setattr lock unlink link rename add_name remove_name reparent search rmdir open } ;
   allow httpd_t httpdcontent : dir { ioctl read write getattr lock add_name remove_name search open } ;
   allow httpd_t httpdcontent : dir { ioctl read write getattr lock add_name remove_name search open } ;
   allow httpd_t httpdcontent : dir { ioctl read write getattr lock add_name remove_name search open } ;
   allow httpd_t httpdcontent : dir { ioctl read write getattr lock add_name remove_name search open } ;
   allow httpd_t httpd_content_type : file { ioctl read getattr lock open } ;
   allow httpd_t httpdcontent : lnk_file { ioctl read write create getattr setattr lock append unlink link rename } ;
   allow httpd_t httpd_content_type : dir { getattr search open } ;
   allow httpd_t httpd_content_type : dir { getattr search open } ;
   allow httpd_t httpd_content_type : dir { ioctl read getattr lock search open } ;
   allow httpd_t httpd_content_type : dir { getattr search open } ;

[root@master ~]#


タイプの中でfile_typeというタイプには、"_t"がついていない(上記★印)。
"_t"がついていないタイプは、複数のタイプの集合である。
seinfo コマンドを実行すると、file_typeが、以下のようなタイプの集合であることがわかる。
このタイプの中にhttpd_sys_content_tが含まれている(■印)。
[root@master ~]# seinfo -afile_type -x
   file_type
      abrt_exec_t
      abrt_initrc_exec_t
      abrt_unit_file_t
      abrt_etc_t
      abrt_var_log_t
      abrt_var_lib_t
      abrt_tmp_t
      abrt_var_cache_t
      abrt_var_run_t
      abrt_dump_oops_exec_t
      abrt_handle_event_exec_t
      -中略-
      httpd_suexec_tmp_t
     ■httpd_sys_content_t
      httpd_sys_htaccess_t
      -以下、略-

さらに、オブジェクトクラスで絞り込みを行う。
-------------------------------
1. fileで絞り込む方法(-c file)
-------------------------------
[root@master html]# sesearch -A -s httpd_t -t httpd_sys_content_t -c file
Found 5 semantic av rules:
   allow httpd_t httpd_content_type : file { ioctl read getattr lock open } ;
   allow httpd_t httpd_sys_content_t : file { ioctl read getattr lock open } ;
   allow httpd_t httpdcontent : file { ioctl read write create getattr setattr lock append unlink link rename open } ;
   allow httpd_t httpdcontent : file { read getattr execute open } ;
   allow httpd_t httpd_content_type : file { ioctl read getattr lock open } ;

-------------------------------
2. dirで絞り込む方法(-c dir)
-------------------------------
[root@master html]# sesearch -A -s httpd_t -t httpd_sys_content_t -c dir
Found 16 semantic av rules:
   allow httpd_t httpd_sys_content_t : dir { ioctl read getattr lock search open } ;
   allow daemon httpd_sys_content_t : dir { getattr search open } ;
   allow httpd_t file_type : dir { getattr search open } ;
   -以下、略-

--------------------------------------
3. lnk_fileで絞り込む方法(-c lnk_file)
--------------------------------------
[root@master html]# sesearch -A -s httpd_t -t httpd_sys_content_t -c lnk_file
Found 3 semantic av rules:
   allow httpd_t httpd_sys_content_t : lnk_file { read getattr } ;
   allow httpd_t httpd_content_type : lnk_file { read getattr } ;
   allow httpd_t httpdcontent : lnk_file { ioctl read write create getattr setattr lock append unlink link rename } ;

6.2 ファイル名遷移の調べ方(File Name Transition)

タイプ遷移に比べると、ファイル名遷移(File Name Transition)の方が、
より厳密にタイプ遷移を指定することが可能になる。

(1)の意味:unconfined_t ドメインのプロセスがvar_log_tタイプのディレクトリ配下にファイル(lastlog)を
      作成すると、そのファイルのタイプはlastlog_t になる。

(2)の意味:unconfined_t ドメインのプロセスがvar_log_tタイプのディレクトリ配下にディレクトリ(lxc)を
      作成すると、そのディレクトリのタイプがcontainer_log_t になる。

タイプ遷移を調べる。
[root@master ~]# sesearch -T -s unconfined_t -t var_log_t
Found 14 named file transition filename_trans:
type_transition unconfined_t var_log_t : file lastlog_t "lastlog";  ★...(1) ファイルの場合
type_transition unconfined_t var_log_t : file rpm_log_t "yum.log";
type_transition unconfined_t var_log_t : dir container_log_t "lxc";  ★...(2) ディレクトリの場合
type_transition unconfined_t var_log_t : file NetworkManager_var_lib_t "wpa_supplicant.log";
type_transition unconfined_t var_log_t : file devicekit_var_log_t "pm-powersave.log";
type_transition unconfined_t var_log_t : file faillog_t "btmp";
type_transition unconfined_t var_log_t : file faillog_t "tallylog";
type_transition unconfined_t var_log_t : file devicekit_var_log_t "pm-suspend.log";
type_transition unconfined_t var_log_t : dir var_log_t "anaconda";
type_transition unconfined_t var_log_t : dir snapperd_data_t ".snapshots";
type_transition unconfined_t var_log_t : file plymouthd_var_log_t "boot.log";
type_transition unconfined_t var_log_t : file faillog_t "faillog";
type_transition unconfined_t var_log_t : file wtmp_t "wtmp";
type_transition unconfined_t var_log_t : file rpm_log_t "up2date";


自分自身(bash)のセキュリティコンテキストを調べる。ドメインがunconfined_tであることがわかる(★印)。
[root@master ~]# ps -Z -p `echo $$`
LABEL                              PID TTY          TIME CMD
unconfined_u:unconfined_r:★unconfined_t:s0-s0:c0.c1023 15501 pts/1 00:00:00 bash

/var/logディレクトリのタイプを調べる。タイプはvar_log_tであることがわかる。
[root@master ~]# ls -lZd /var/log
drwxr-xr-x. root root system_u:object_r:★var_log_t:s0   /var/log

上記(1)について確認する。/var/log配下にlastlogというファイルを作成する。
[root@master ~]# touch /var/log/lastlog

作成したファイルのタイプを確認する。タイプがlastlog_tであることがわかる。
[root@master ~]# ls -lZ /var/log/lastlog
-rw-r--r--. root root system_u:object_r:★lastlog_t:s0   /var/log/lastlog

別の名前のファイルを作成する。
[root@master ~]# touch /var/log/hoge

タイプがlastlog_t ではなく、var_log_tであることがわかる。
[root@master ~]# ls -lZ /var/log/hoge
-rw-r--r--. root root unconfined_u:object_r:★var_log_t:s0 /var/log/hoge


上記(2)について確認する。/var/log配下にlxcというディレクトリを作成する。
[root@master ~]# mkdir /var/log/lxc

作成したディレクトリのタイプを確認する。タイプがcontainer_log_t であることがわかる。
[root@master ~]# ls -lZd /var/log/lxc/
drwxr-xr-x. root root unconfined_u:object_r:★container_log_t:s0 /var/log/lxc/

別の名前のディレクトリを作成する。
[root@master ~]# mkdir /var/log/lll

タイプがcontainer_log_tではなく、var_log_tであることがわかる。
[root@master ~]# ls -lZd /var/log/lll
drwxr-xr-x. root root unconfined_u:object_r:★var_log_t:s0 /var/log/lll

7 ポリシ情報の表示(seinfo)

7.2 ドメインの確認方法

[root@master ~]# seinfo -adomain -x
   domain
      abrt_t
      abrt_dump_oops_t
      abrt_handle_event_t
      abrt_helper_t
      -中略-
      httpd_t
      httpd_helper_t
      httpd_php_t
      httpd_rotatelogs_t
      httpd_suexec_t
      httpd_sys_script_t
      httpd_user_script_t
      httpd_passwd_t
      httpd_unconfined_script_t
      -以下、略-

7.2 タイプの確認方法

[root@master ~]# seinfo -thttpd_t -x
   httpd_t
      nsswitch_domain
      can_change_object_identity
      corenet_unlabeled_type
      domain
      kernel_system_state_reader
      netlabel_peer_type
      daemon
      syslog_client_type
      pcmcia_typeattr_7
      pcmcia_typeattr_6
      pcmcia_typeattr_5
      pcmcia_typeattr_4
      pcmcia_typeattr_3
      pcmcia_typeattr_2
      pcmcia_typeattr_1
      sepgsql_client_type
   Aliases
      phpfpm_t

7.3 Permissiveドメインの確認方法

[root@master ~]# seinfo --permissive -x

Permissive Types: 6
   blkmapd_t
   hsqldb_t
   ipmievd_t
   sanlk_resetd_t
   systemd_hwdb_t
   targetd_t
[root@master ~]#

8 httpdをデフォルトポート番号(80)以外のポート番号で動かす方法

8.1 SELinux設定変更前の状態

SElinuxがEnforcingの状態で次のことを確認する。
- httpdがListenポート番号として8888番を使えるかどうか?
結論として、デフォルトのままでは使えない。8.2または8.3で使えるようにする。

SElinuxの状態を確認する。
[root@master ~]# getenforce
Enforcing

httpdサーバのListenポート番号を変更(80->8888)する。
[root@master ~]# cat /etc/httpd/conf/httpd.conf|grep Listen
# Listen: Allows you to bind Apache to specific IP addresses and/or
# Change this to Listen on specific IP addresses as shown below to
#Listen 80
Listen 8888

httpdを起動する。httpdの起動が失敗したことがわかる。
[root@master ~]# systemctl start httpd
Job for httpd.service failed because the control process exited with error code. See "systemctl status httpd.service" and "journalctl -xe" for details.
[root@master ~]#

httpd失敗の原因をjournalctlコマンドで確認する。bindシステムコールで"Permission denied"が発生していることがわかる(★印)。
[root@master ~]# journalctl -u httpd
-中略-
 3月 26 10:08:40 master httpd[33016]: [Sun Mar 26 10:08:40.308429 2017] [alias:warn] [pid 33016] AH00671: The ScriptAlias directive in /etc/httpd/conf/httpd.
 3月 26 10:08:40 master httpd[33016]: [Sun Mar 26 10:08:40.310101 2017] [alias:warn] [pid 33016] AH00671: The ScriptAlias directive in /etc/httpd/conf/httpd.
 3月 26 10:08:40 master httpd[33016]: [Sun Mar 26 10:08:40.310143 2017] [alias:warn] [pid 33016] AH00671: The ScriptAlias directive in /etc/httpd/conf/httpd.
 3月 26 10:08:40 master httpd[33016]: [Sun Mar 26 10:08:40.310158 2017] [alias:warn] [pid 33016] AH00671: The ScriptAlias directive in /etc/httpd/conf/httpd.
 3月 26 10:08:40 master httpd[33016]: AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 192.168.0.10. Set the 'Ser
 3月 26 10:08:40 master httpd[33016]: (13)Permission denied: AH00072: make_sock: ★could not bind to address [::]:8888
 3月 26 10:08:40 master httpd[33016]: (13)Permission denied: AH00072: make_sock: ★could not bind to address 0.0.0.0:8888
 3月 26 10:08:40 master httpd[33016]: no listening sockets available, shutting down
 3月 26 10:08:40 master httpd[33016]: AH00015: Unable to open logs
 3月 26 10:08:40 master systemd[1]: httpd.service: main process exited, code=exited, status=1/FAILURE
 3月 26 10:08:40 master kill[33018]: kill: cannot find process ""
 3月 26 10:08:40 master systemd[1]: httpd.service: control process exited, code=exited status=1
 3月 26 10:08:40 master systemd[1]: Failed to start The Apache HTTP Server.
 3月 26 10:08:40 master systemd[1]: Unit httpd.service entered failed state.
 3月 26 10:08:40 master systemd[1]: httpd.service failed.
 -以下、略-


httpd失敗の原因をaudit.logでも確認してみる。bindシステムコールでEACCESが発生していることがわかる(★印)。
[root@master ~]# ausearch -i -if /var/log/audit/audit.log |less
----
type=SERVICE_START msg=audit(2017年03月26日 10:03:24.529:6087) : pid=1 uid=root auid=unset ses=unset subj=system_u:system_r:init_t:s0 msg='unit=httpd comm=sy
stemd exe=/usr/lib/systemd/systemd hostname=? addr=? terminal=? res=failed'
----
type=SYSCALL msg=audit(2017年03月26日 10:03:24.391:6086) : arch=x86_64 syscall=bind★ success=no exit=EACCES(許可がありません) a0=0x3 a1=0x7f163cfb4cf8 a2=0x10
 a3=0x7ffcbc0743cc items=0 ppid=1 pid=32961 auid=unset uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=(none) ses=unset comm=httpd exe=/usr/sbin/httpd subj=system_u:system_r:httpd_t:s0 key=(null)
type=AVC msg=audit(2017年03月26日 10:03:24.391:6086) : avc:  denied  { name_bind } for  pid=32961 comm=httpd src=8888 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:unreserved_port_t:s0 tclass=tcp_socket
----
type=SYSCALL msg=audit(2017年03月26日 10:03:24.390:6085) : arch=x86_64 syscall=bind★ success=no exit=EACCES(許可がありません) a0=0x4 a1=0x7f163cfb4db8 a2=0x1c a3=0x7ffcbc074180 items=0 ppid=1 pid=32961 auid=unset uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=(none) ses=unset comm=httpd exe=/usr/sbin/httpd subj=system_u:system_r:httpd_t:s0 key=(null)
type=AVC msg=audit(2017年03月26日 10:03:24.390:6085) : avc:  denied  { name_bind } for  pid=32961 comm=httpd src=8888 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:unreserved_port_t:s0 tclass=tcp_socket

8.2 SELinuxの設定変更による方法

SELinuxの設定変更をして、httpdがListenできるポート番号を追加する。
ここでは、8888番ポートを追加する例を示す。

httpがListenできるポート番号を確認する。
[root@master ~]# semanage port -l|grep -w http_port_t
http_port_t                    tcp      80, 81, 443, 488, 8008, 8009, 8443, 9000

[root@master ~]# seinfo --portcon=8888
        portcon tcp 1024-32767 system_u:object_r:unreserved_port_t:s0
        portcon udp 1024-32767 system_u:object_r:unreserved_port_t:s0

httpがListenできるポート番号(8888)を追加する。
[root@master ~]# semanage port -a -t http_port_t -p tcp 8888

ポート番号を確認する。8888番が追加されたことが確認できる(★印)。
[root@master ~]# semanage port -l|grep -w http_port_t
http_port_t                    tcp      ★8888, 80, 81, 443, 488, 8008, 8009, 8443, 9000

SElinuxの状態を確認する。Enforcingになっていることがわかる。
[root@master ~]# getenforce
Enforcing

httpdを起動する。今度は起動できた。
[root@master ~]# systemctl start httpd
[root@master ~]#

ポート番号を確認する。httpdが8888番を使っていることがわかる。
[root@master ~]# lsof -i:8888
COMMAND   PID   USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
httpd   33085   root    4u  IPv6 223046      0t0  TCP *:ddi-tcp-1 (LISTEN)
httpd   33086 apache    4u  IPv6 223046      0t0  TCP *:ddi-tcp-1 (LISTEN)
httpd   33087 apache    4u  IPv6 223046      0t0  TCP *:ddi-tcp-1 (LISTEN)
httpd   33088 apache    4u  IPv6 223046      0t0  TCP *:ddi-tcp-1 (LISTEN)
httpd   33089 apache    4u  IPv6 223046      0t0  TCP *:ddi-tcp-1 (LISTEN)
httpd   33090 apache    4u  IPv6 223046      0t0  TCP *:ddi-tcp-1 (LISTEN)
[root@master ~]#

8888番ポートにアクセスする。
[root@master ~]# cat /var/www/html/index.html
test
[root@master ~]# curl http://localhost:8888
test

8.3 httpdの定義ファイルを変更する方法

ここでは、SELinuxの設定変更をしない例を示す。

httpがListenできるポート番号を確認する。ここでは9000番ポートを使う(★印)。
[root@master ~]# semanage port -l|grep -w http_port_t
http_port_t                    tcp      80, 81, 443, 488, 8008, 8009, 8443, ★9000

httpdが9000番ポートでListenするように編集する。
[root@master ~]# cat /etc/httpd/conf/httpd.conf|grep Listen
-中略-
Listen 9000

SELinuxの状態を確認する。Enforcingであることがわかる。
[root@master ~]# getenforce
Enforcing

httpdを起動する。起動できたたことがわかる。
[root@master ~]# systemctl start httpd
[root@master ~]#

ポート番号を確認する。httpdが9000番ポートでListenしていることがわかる。
[root@master ~]# lsof -i:9000
COMMAND   PID   USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
httpd   33186   root    4u  IPv6 227510      0t0  TCP *:cslistener (LISTEN)
httpd   33187 apache    4u  IPv6 227510      0t0  TCP *:cslistener (LISTEN)
httpd   33188 apache    4u  IPv6 227510      0t0  TCP *:cslistener (LISTEN)
httpd   33189 apache    4u  IPv6 227510      0t0  TCP *:cslistener (LISTEN)
httpd   33190 apache    4u  IPv6 227510      0t0  TCP *:cslistener (LISTEN)
httpd   33191 apache    4u  IPv6 227510      0t0  TCP *:cslistener (LISTEN)

9000番ポートにアクセスする。
[root@master ~]# cat /var/www/html/index.html
test
[root@master ~]# curl http://localhost:9000
test

9 正しいルール、タイプの確認方法

9.1 正しいルールの確認方法(audit2why)

アクセス拒否の理由を調べる。1行が長いので折り返しています。
テスト環境の設定が悪いので、コマンドが誤ったアクセス拒否理由を出力している(TEルール作成を指示している)。
本来は、TEルールを作成するのではなく、index.htmlのタイプをhttpd_sys_content_tに変更するのが正解だと思う。
[root@master ~]# ausearch -m avc -ts today |audit2why
type=AVC msg=audit(1490574054.437:1121): avc:  denied  { getattr } for  
    pid=6451 
    comm="httpd" 
    path="/var/www/html/kernel-3.10.0-514.el7/linux-3.10.0-514.el7.centos.x86_64/HTML/index.html" 
    dev="sda3" 
    ino=9952163 
    scontext=system_u:system_r:httpd_t:s0 
    tcontext=unconfined_u:object_r:admin_home_t:s0 
    tclass=file

        Was caused by:
                Missing type enforcement (TE) allow rule.

                You can use audit2allow to generate a loadable module to allow this access.
-以下、略-

9.2 正しいタイプの確認方法(matchpathcon)

ファイルやディレクトリーに正しいセキュリティコンテキストが設定されているかどうかをチェックする。

初期状態を確認する。
[root@master ~]# ls -Z /var/www/html
drwxr-xr-x. root root unconfined_u:object_r:admin_home_t:s0 docker-1.12.5-14
drwxr-xr-x. root root unconfined_u:object_r:admin_home_t:s0 etcd-3.1.0-2
-rw-r--r--. root root unconfined_u:object_r:samba_share_t:s0 index.html
drwxr-xr-x. root root unconfined_u:object_r:admin_home_t:s0 kernel-3.10.0-514.el7
drwxr-xr-x. root root unconfined_u:object_r:httpd_sys_content_t:s0 kubernetes1.4

正しいセキュリティコンテキストが設定されているかどうかをチェックする。
それぞれ★印以降のセキュリティコンテキストを設定すべき、との表示が出力されれていることがわかる。
[root@master ~]# matchpathcon -V /var/www/html/*
/var/www/html/docker-1.12.5-14 has context unconfined_u:object_r:admin_home_t:s0, should be ★system_u:object_r:httpd_sys_content_t:s0
/var/www/html/etcd-3.1.0-2 has context unconfined_u:object_r:admin_home_t:s0, should be ★system_u:object_r:httpd_sys_content_t:s0
/var/www/html/index.html has context unconfined_u:object_r:samba_share_t:s0, should be ★system_u:object_r:httpd_sys_content_t:s0
/var/www/html/kernel-3.10.0-514.el7 has context unconfined_u:object_r:admin_home_t:s0, should be ★system_u:object_r:httpd_sys_content_t:s0
/var/www/html/kubernetes1.4 verified.
[root@master ~]#


テストとして、index.htmlのタイプだけを正しいセキュリティコンテキスト変更する。
[root@master ~]# restorecon -v /var/www/html/index.html
restorecon reset /var/www/html/index.html context unconfined_u:object_r:samba_share_t:s0->unconfined_u:object_r:httpd_sys_content_t:s0

index.htmlのセキュリティコンテキストを確認する。正しいタイプに設定されたことがわかる(★印)。
[root@master ~]# ls -lZ /var/www/html/index.html
-rw-r--r--. root root unconfined_u:object_r:★httpd_sys_content_t:s0 /var/www/html/index.html
[root@master ~]#

10 ドメイン遷移の調べ方

10.1 遷移可能なドメイン一覧を調べる方法

httpd_tドメインが遷移できるドメインを調べる。
(1)は、httpd_tドメインがantivirus_exec_tタイプのファイルを実行すると、
antivirus_tというタイプにドメイン遷移する、という意味。
[root@master selinux]# sepolicy transition -s httpd_t
httpd_t @ antivirus_exec_t --> antivirus_t  ★...(1)
httpd_t @ sepgsql_trusted_proc_exec_t --> sepgsql_trusted_proc_t
httpd_t @ httpd_php_exec_t --> httpd_php_t
-以下、略-

10.2 遷移可能かどうかを調べる方法

httpd_tドメインがhttpd_php_tドメインに遷移可能かどうかを調べる。遷移可能であることがわかる。
[root@master selinux]# sepolicy transition -s httpd_t -t httpd_php_t
httpd_t @ httpd_php_exec_t --> httpd_php_t

12 ブール値

redhatマニュアル

ブール値を使うと、SELinux ポリシー記述の知識がなくても、ランタイム時にSELinux ポリシーの一部を変更できます。これにより、SELinux ポリシーの再ロードや再コンパイルをせずに、NFS ファイルシステムへのサービスによるアクセスを許可するといった変更が可能になります。

12.1 ブール値の一覧表示方法

[root@master ~]# semanage boolean -l
SELinux boolean                状態  初期値 説明

privoxy_connect_any            (オン   ,   オン)  privoxy がすべての TCP ポートに接続できるかどうかを指定します。
smartmon_3ware                 (オフ   ,   オフ)  smartmon が 3ware コントローラーにおいてデバイスをサポートできるかどうかを指定しま
す。
-以下、略-

13 Docker,KubernetesのSELinux利用状況

13.1 ドメイン

[root@master ~]# ps -Z -C kube-apiserver,kube-scheduler,kube-controller-manager,kube-proxy,kubelet
LABEL                              PID TTY          TIME CMD
system_u:system_r:unconfined_service_t:s0 75435 ? 00:00:11 kube-apiserver
system_u:system_r:unconfined_service_t:s0 75448 ? 00:00:12 kube-scheduler
system_u:system_r:unconfined_service_t:s0 75455 ? 00:00:16 kube-controller
system_u:system_r:unconfined_service_t:s0 75468 ? 00:00:22 kube-proxy
system_u:system_r:unconfined_service_t:s0 75592 ? 00:00:08 kubelet

[root@master ~]# ps -Z -C etcd
LABEL                              PID TTY          TIME CMD
system_u:system_r:initrc_t:s0    75419 ?        00:00:13 etcd

[root@master ~]# ps -Z -C dockerd-current,docker-containerd-current
LABEL                              PID TTY          TIME CMD
system_u:system_r:container_runtime_t:s0 75504 ? 00:00:08 dockerd-current
system_u:system_r:container_runtime_t:s0 75515 ? 00:00:01 docker-containe

13.2 タイプ

[root@master ~]# ls -lZ /etc/kubernetes/
-rw-r--r--. root root system_u:object_r:etc_t:s0       apiserver
-rw-r--r--. root root system_u:object_r:etc_t:s0       config
-rw-r--r--. root root system_u:object_r:etc_t:s0       controller-manager
-rw-r--r--. root root system_u:object_r:etc_t:s0       kubelet
-rw-r--r--. root root system_u:object_r:etc_t:s0       proxy
-rw-r--r--. root root system_u:object_r:etc_t:s0       scheduler

[root@master ~]# ls -lZ /etc/etcd/
-rw-r--r--. root root unconfined_u:object_r:etc_t:s0   etcd.conf

[root@master ~]# ls -lZ /etc/sysconfig/docker*
-rw-r--r--. root root system_u:object_r:etc_t:s0       /etc/sysconfig/docker
-rw-r--r--. root root system_u:object_r:etc_t:s0       /etc/sysconfig/docker-network
-rw-r--r--. root root system_u:object_r:etc_t:s0       /etc/sysconfig/docker-storage
-rw-r--r--. root root system_u:object_r:etc_t:s0       /etc/sysconfig/docker-storage-setup

Z 参考情報

SELinux リファレンス・ポリシーで新しいドメインを作成する
SELinuxを独学したよ
Linux OS のセキュリティ-2
SELINUX ユーザーおよび管理者のガイド
CentOS SELINUX
SELinuxの構成および使用
SELinux/Tutorials/How does a process get into a certain context

19
23
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
23