redhat 系 Linux のセキュリティーでは、代表的なモノとして扱われる SELinux。しかし、SELinux は redhat 系のサーバー管理者がしばしば躓く項目と言われている。

そこで今回は、SELinux の基本的な考え方とよく使う設定、GUI での設定方法などを紹介しようと思う。

 

※ SELinux の詳細は、ココココをご覧下さい。

※ このページで使用している『SELinux のラベル』『コンテキスト』『SELinux タイプ』は事実上、全て同じもので、『XXXXX_t』で表します。

 

 

SELinux はホワイトリスト形式

一般的な PC 用のセキュリティーソフトは、ブラックリスト形式を採用しています。セキュリティーソフトの制作会社がブラックリストの指定、つまり指名手配の様な事を行い、セキュリティーソフトが補足や削除などの対策を行い、PC の状態を安全に保つことを目的としています。そのため、ユーザーは殆ど行うことが無い為、運用が簡単に行えるのが特徴です。しかし、セキュリティーソフトの制作会社が対象となるウイルスの存在を識別している事が必要最低限となる為、ウイルスが特定の組織のみを対象としたモノで、一般には存在が知られていない場合などには全くの無防備になる事があり、最悪なケースでは発見されるまで数年間も放置される事もあります。

 

一方、ホワイトリスト形式は許可形式とも言われ、許可した事以外は全て不許可になる為、相手の存在を識別する必要はありません。しかし無闇に許可してしてしまうと意味を無くしてしまう為、何を許可するかの知識が必要になります。事実、幾つかのサーバーソフトウェアは全てを許可する事により、SELinux による保護を拒否しているモノも存在します。

 

 

SELinux はカーネルに干渉する

Linux でもシステムリソースは、カーネルが管理しています。そのため、ハードディスクのファイルや物理メモリ上の共有メモリ、ネットワークデバイスを利用したインターネットへの通信もカーネルを経由する事になり、それらを利用する為には、カーネルが提供するシステムコールを利用する必要があります。また、権限の昇格などのドメイン遷移やプロセスに対する処理などもシステムコールを利用します。

 

SELinux は、このシステムコールに干渉して許可/不許可を決定するモジュールであり、いわゆるセキュリティーソフトではありません。外見上はカーネルの一部として動作するため、全てのプロセス(実行中のプログラム)が SELinux の監視対象になります。

 

こういった都合上、SELinux は、ウイルス発見や駆除などは一切行いません。

 

※ システムコールは関数ではなく、カーネルに対する依頼です。例えば write() には、ファイルなどに直接書き込む機能はなく、実際に行われるのはカーネルへのバッファ転送と描き込み依頼であり、バッファからファイルへの描き込みを行うのはカーネルです。

※ C 言語でファイルを開く fopen() は 内部でシステ−ムコールの open() を呼び出し、その他のプログラミング言語でも同様にシステ−ムコールの open() を呼び出します。

 

 

SELinux の利点

代表的な WEB サーバーである、Apache(httpd) を例に用いて説明します。例えば『http://server-address/』としてアクセスした場合、『/var/www/html/index.html』が読み込まれます。つまり、トップページが『/var/www/html/index.html』であるワケです。ここで仮に、Apache(httpd) にバッファオーバーフローを利用して任意のコードが実行できる重大な脆弱性があったとします。悪意のあるクラッカーがこの脆弱性を利用してトップページの改竄を企てた場合、SELinux が有効で設定がデフォルトである時、この企ては必ず失敗します。これは、Apache(httpd) からプログラム(コマンドやスクリプト)を起動した場合でも同じです。

 

理由は至って簡単で『/var/www/html/』への書き込みが禁止されている事、Apache(httpd) からコマンドの使用が禁止されている事、スタックやヒープからのコードの実行が禁止されている事などと、Apache(httpd) の子孫プロセスにも同様の強制が働く事が挙げられます。勿論、権限の昇格やドメイン遷移なども禁止項目に含まれます。

 

※ ココでの例は、『/var/www/html/index.html』が Apache でトップページに設定されている場合です。(デフォルト)

 

ここで少し整理してみしょう。

 

  • SELinux はホワイトリスト形式で、許可した事以外は全て禁止項目になる。
  • 強制力はカーネルレベルで発生し、回避する方法が事実上存在しない。(勿論、カーネル自体に脆弱性がある場合は別ですが、プロセスの実行やファイルの読み書きもカーネルを経由する為、回避する事は非常に困難です。)
  • セキュリティーホール自体がプロセス内で発生する為、カーネルの監視対象である。

 

しかし無知な人はこう言うかも知れません。「そんなものはアセンブラを利用すれば良い」と。アセンブラでもファイルのアクセスにはシステムコールを利用するのですが、その部分でもアセンブラで行うのでしょうか? Linux で利用されるファイルシステムは非常に多岐に渡り、その中には Windows のファイルシステムさえ含まれます。今度はデバイスドライバを自作するのでしょうか? しかも Linux で利用できる CPU は Intel 互換 CPU だけではありあません。それらもカバーするアセンブラを作成するのでしょうか?

 

実際には、アセンブラで作成されたウイルスが存在した事もあるそうですが、コードが有効な Linux が非常に少なく、実質的な被害は与えられなかったそうです。まあ、作成にも莫大なコストが発生するにも関わらず、有効な攻撃手段にならないので当然の結果と言えるでしょう。

 

とは言え、SELinux を過信し過ぎるのも感心出来ません。SELinux は最後の砦であり、前衛を任せる存在ではありません。ファイヤーウォールやサーバーの ACL(アクセス制御リスト)などの併用するようにしましょう。

 

SELinux の基本的な考え方

SELinux は実際にはどのようにしてプロセスを監視しているのでしょうか? ここでも Apache を例に説明していきます。

 

※ ココからは全て、管理者権限で端末から実行しています。(SELinux は有効な状態です)

 

先ずはサービスファイルがある『/usr/lib/systemd/system/』に移動します。

 

# cd /usr/lib/systemd/system/

 

サービスファイルの apache を探します。

 

# grep -i apache *.service
htcacheclean.service:Description=Disk Cache Cleaning Daemon for Apache HTTP Server
htcacheclean.service:User=apache
httpd.service:Description=The Apache HTTP Server
#

 

ここで『Description=The Apache HTTP Server』とあるので、httpd.service がサービスファイルである事が判明しました。

 

『httpd.service』の中身を見ます。

 

# cat httpd.service
# It's not recommended to modify this file in-place, because it will be
# overwritten during package upgrades. If you want to customize, the best
# way is to create a file "/etc/systemd/system/httpd.service",
# containing
# .include /lib/systemd/system/httpd.service
# ...make your changes here...
# For more info about custom unit files, see
# http://fedoraproject.org/wiki/Systemd#How_do_I_customize_a_unit_file.2F_add_a_custom_unit_file.3F
# For example, to pass additional options (for instance, -D definitions) to the
# httpd binary at startup, you need to create a file named
# “/etc/systemd/system/httpd.service” containing:
# .include /lib/systemd/system/httpd.service
# [Service]
# Environment=OPTIONS=-DMY_DEFINE[Unit]
Description=The Apache HTTP Server
After=network.target remote-fs.target nss-lookup.target[Service]
Type=notify
Environment=LANG=C
ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND
ExecReload=/usr/sbin/httpd $OPTIONS -k graceful
# Send SIGWINCH for graceful stop
KillSignal=SIGWINCH
KillMode=mixed
PrivateTmp=true[Install]
WantedBy=multi-user.target

 

ここで『ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND』とあるので、『/usr/sbin/httpd』が、デーモンの本体である事が判明します。

 

『/usr/sbin/httpd』の SELinux のラベルを見ます。

 

# ls -Z /usr/sbin/httpd
system_u:object_r:httpd_exec_t:s0

 

※ SELinux 関連の情報を調べる場合、大文字の『Z』を使用します。

 

ここで Apache の SELinux ラベルが『httpd_t』である事が判明しました。(_exec はファイルに対してのみ使用される部分なので無視します。)

 

Apache が起動していない場合は、起動します。

 

# systemctl start httpd.service

 

確認の為、実行中の Apache の SELinux ラベルを確認します。

 

# ps auxZ | grep httpd
system_u:system_r:httpd_t:s0 root 2871 0.0 0.3 528744 27060 ? Ss 7月17 0:02 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 root 2988 0.0 0.1 52980 12228 ? S 7月17 0:00 /usr/libexec/nss_pcache 196611 off /etc/httpd/alias
system_u:system_r:httpd_t:s0 apache 3060 0.0 0.2 528672 20432 ? S 7月17 0:00 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 apache 3061 0.0 0.4 547920 33728 ? S 7月17 0:00 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 apache 3062 0.0 0.4 547920 33724 ? S 7月17 0:00 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 apache 3063 0.0 0.4 547920 33728 ? S 7月17 0:00 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 apache 3064 0.0 0.4 547920 33744 ? S 7月17 0:00 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 apache 3065 0.0 0.4 547920 33748 ? S 7月17 0:00 /usr/sbin/httpd -DFOREGROUND

 

このプロセスは、公開ファイル(public_content_t と public_rw_content_t)を除き、httpd_XXXXX_t のコンテキストを持つファイルにだけ、アクセスが可能です。

 

では次に、SELinux のファイルに対する設定を見てみます。(勿論、許可リストです)

 

# semanage fcontext -l | grep httpd
/etc/BackupPC(/.*)? all files system_u:object_r:httpd_sys_script_rw_t:s0
/etc/WebCalendar(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
/etc/apache(2)?(/.*)? all files system_u:object_r:httpd_config_t:s0
/etc/apache-ssl(2)?(/.*)? all files system_u:object_r:httpd_config_t:s0
/etc/cherokee(/.*)? all files system_u:object_r:httpd_config_t:s0
/etc/drupal.* all files system_u:object_r:httpd_sys_rw_content_t:s0
/etc/glpi(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
/etc/horde(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
/etc/htdig(/.*)? all files system_u:object_r:httpd_sys_content_t:s0
/etc/httpd(/.*)? all files system_u:object_r:httpd_config_t:s0
/etc/httpd/alias(/.*)? all files system_u:object_r:cert_t:s0
/etc/httpd/conf/keytab regular file system_u:object_r:httpd_keytab_t:s0
/etc/httpd/logs all files system_u:object_r:httpd_log_t:s0
/etc/httpd/modules all files system_u:object_r:httpd_modules_t:s0
/etc/init\.d/cherokee regular file system_u:object_r:httpd_initrc_exec_t:s0
/etc/lighttpd(/.*)? all files system_u:object_r:httpd_config_t:s0
/etc/mock/koji(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
/etc/nginx(/.*)? all files system_u:object_r:httpd_config_t:s0
/etc/owncloud(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
/etc/rc\.d/init\.d/httpd regular file system_u:object_r:httpd_initrc_exec_t:s0
/etc/rc\.d/init\.d/lighttpd regular file system_u:object_r:httpd_initrc_exec_t:s0
/etc/thttpd\.conf regular file system_u:object_r:httpd_config_t:s0
/etc/vhosts regular file system_u:object_r:httpd_config_t:s0
/etc/z-push(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
/etc/zabbix/web(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
/opt/.*\.cgi regular file system_u:object_r:httpd_sys_script_exec_t:s0
/opt/dirsrv/var/run/dirsrv/dsgw/cookies(/.*)? all files system_u:object_r:httpd_var_run_t:s0
/srv/([^/]*/)?www(/.*)? all files system_u:object_r:httpd_sys_content_t:s0
/srv/([^/]*/)?www/logs(/.*)? all files system_u:object_r:httpd_log_t:s0
/srv/gallery2(/.*)? all files system_u:object_r:httpd_sys_content_t:s0
/srv/gallery2/smarty(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
/usr/.*\.cgi regular file system_u:object_r:httpd_sys_script_exec_t:s0
/usr/bin/htsslpass regular file system_u:object_r:httpd_helper_exec_t:s0
/usr/bin/httpd regular file system_u:object_r:publicfile_exec_t:s0
/usr/bin/mongrel_rails regular file system_u:object_r:httpd_exec_t:s0
/usr/lib/apache(/.*)? all files system_u:object_r:httpd_modules_t:s0
/usr/lib/apache(2)?/suexec(2)? regular file system_u:object_r:httpd_suexec_exec_t:s0
/usr/lib/apache-ssl/.+ regular file system_u:object_r:httpd_exec_t:s0
/usr/lib/apache2/modules(/.*)? all files system_u:object_r:httpd_modules_t:s0
/usr/lib/cgi-bin(/.*)? all files system_u:object_r:httpd_sys_script_exec_t:s0
/usr/lib/cgi-bin/(nph-)?cgiwrap(d)? regular file system_u:object_r:httpd_suexec_exec_t:s0
/usr/lib/cherokee(/.*)? all files system_u:object_r:httpd_modules_t:s0
/usr/lib/httpd(/.*)? all files system_u:object_r:httpd_modules_t:s0
/usr/lib/lighttpd(/.*)? all files system_u:object_r:httpd_modules_t:s0
/usr/lib/systemd/system/httpd.* regular file system_u:object_r:httpd_unit_file_t:s0
/usr/lib/systemd/system/jetty.* regular file system_u:object_r:httpd_unit_file_t:s0
/usr/lib/systemd/system/nginx.* regular file system_u:object_r:httpd_unit_file_t:s0
/usr/lib/systemd/system/php-fpm.* regular file system_u:object_r:httpd_unit_file_t:s0
/usr/lib/systemd/system/thttpd.* regular file system_u:object_r:httpd_unit_file_t:s0
/usr/libexec/httpd-ssl-pass-dialog regular file system_u:object_r:httpd_passwd_exec_t:s0
/usr/sbin/apache(2)? regular file system_u:object_r:httpd_exec_t:s0
/usr/sbin/apache-ssl(2)? regular file system_u:object_r:httpd_exec_t:s0
/usr/sbin/cherokee regular file system_u:object_r:httpd_exec_t:s0
/usr/sbin/htcacheclean regular file system_u:object_r:httpd_exec_t:s0
/usr/sbin/httpd(\.worker)? regular file system_u:object_r:httpd_exec_t:s0
/usr/sbin/httpd\.event regular file system_u:object_r:httpd_exec_t:s0
/usr/sbin/lighttpd regular file system_u:object_r:httpd_exec_t:s0
/usr/sbin/nginx regular file system_u:object_r:httpd_exec_t:s0
/usr/sbin/php-fpm regular file system_u:object_r:httpd_exec_t:s0
/usr/sbin/rotatelogs regular file system_u:object_r:httpd_rotatelogs_exec_t:s0
/usr/sbin/suexec regular file system_u:object_r:httpd_suexec_exec_t:s0
/usr/sbin/thttpd regular file system_u:object_r:httpd_exec_t:s0
/usr/share/doc/ghc/html(/.*)? all files system_u:object_r:httpd_sys_content_t:s0
/usr/share/drupal.* all files system_u:object_r:httpd_sys_content_t:s0
/usr/share/glpi(/.*)? all files system_u:object_r:httpd_sys_content_t:s0
/usr/share/htdig(/.*)? all files system_u:object_r:httpd_sys_content_t:s0
/usr/share/icecast(/.*)? all files system_u:object_r:httpd_sys_content_t:s0
/usr/share/jetty/bin/jetty.sh regular file system_u:object_r:httpd_exec_t:s0
/usr/share/joomla(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
/usr/share/ntop/html(/.*)? all files system_u:object_r:httpd_sys_content_t:s0
/usr/share/openca/htdocs(/.*)? all files system_u:object_r:httpd_sys_content_t:s0
/usr/share/selinux-policy[^/]*/html(/.*)? all files system_u:object_r:httpd_sys_content_t:s0
/usr/share/system-config-httpd/system-config-httpd regular file system_u:object_r:bin_t:s0
/usr/share/wordpress-mu/wp-config\.php regular file system_u:object_r:httpd_sys_script_exec_t:s0
/usr/share/wordpress-mu/wp-content(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
/usr/share/wordpress/.*\.php regular file system_u:object_r:httpd_sys_script_exec_t:s0
/usr/share/wordpress/wp-content/upgrade(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
/usr/share/wordpress/wp-content/uploads(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
/usr/share/wordpress/wp-includes/.*\.php regular file system_u:object_r:httpd_sys_script_exec_t:s0
/usr/share/z-push(/.*)? all files system_u:object_r:httpd_sys_content_t:s0
/var/cache/httpd(/.*)? all files system_u:object_r:httpd_cache_t:s0
/var/cache/lighttpd(/.*)? all files system_u:object_r:httpd_cache_t:s0
/var/cache/mason(/.*)? all files system_u:object_r:httpd_cache_t:s0
/var/cache/mediawiki(/.*)? all files system_u:object_r:httpd_cache_t:s0
/var/cache/mod_.* all files system_u:object_r:httpd_cache_t:s0
/var/cache/mod_gnutls(/.*)? all files system_u:object_r:httpd_cache_t:s0
/var/cache/mod_proxy(/.*)? all files system_u:object_r:httpd_cache_t:s0
/var/cache/mod_ssl(/.*)? all files system_u:object_r:httpd_cache_t:s0
/var/cache/php-.* all files system_u:object_r:httpd_cache_t:s0
/var/cache/php-eaccelerator(/.*)? all files system_u:object_r:httpd_cache_t:s0
/var/cache/php-extend-cache(/.*)? all files system_u:object_r:httpd_cache_t:s0
/var/cache/php-mmcache(/.*)? all files system_u:object_r:httpd_cache_t:s0
/var/cache/rt(3|4)(/.*)? all files system_u:object_r:httpd_cache_t:s0
/var/cache/ssl.*\.sem regular file system_u:object_r:httpd_cache_t:s0
/var/lib/cacti/rra(/.*)? all files system_u:object_r:httpd_sys_content_t:s0
/var/lib/cherokee(/.*)? all files system_u:object_r:httpd_var_lib_t:s0
/var/lib/dav(/.*)? all files system_u:object_r:httpd_var_lib_t:s0
/var/lib/dokuwiki(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
/var/lib/drupal.* all files system_u:object_r:httpd_sys_rw_content_t:s0
/var/lib/glpi(/.*)? all files system_u:object_r:httpd_var_lib_t:s0
/var/lib/graphite-web(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
/var/lib/htdig(/.*)? all files system_u:object_r:httpd_sys_content_t:s0
/var/lib/httpd(/.*)? all files system_u:object_r:httpd_var_lib_t:s0
/var/lib/ipsilon(/.*)? all files system_u:object_r:httpd_var_lib_t:s0
/var/lib/lighttpd(/.*)? all files system_u:object_r:httpd_var_lib_t:s0
/var/lib/mod_security(/.*)? all files system_u:object_r:httpd_var_lib_t:s0
/var/lib/moodle(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
/var/lib/nginx(/.*)? all files system_u:object_r:httpd_var_lib_t:s0
/var/lib/openshift/\.httpd\.d(/.*)? all files system_u:object_r:httpd_config_t:s0
/var/lib/openshift/\.log/httpd(/.*)? all files system_u:object_r:httpd_log_t:s0
/var/lib/owncloud(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
/var/lib/php(/.*)? all files system_u:object_r:httpd_var_lib_t:s0
/var/lib/php/session(/.*)? all files system_u:object_r:httpd_var_run_t:s0
/var/lib/php/wsdlcache(/.*)? all files system_u:object_r:httpd_var_run_t:s0
/var/lib/pootle/po(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
/var/lib/roundcubemail(/.*)? all files system_u:object_r:httpd_var_lib_t:s0
/var/lib/rt(3|4)/data/RT-Shredder(/.*)? all files system_u:object_r:httpd_var_lib_t:s0
/var/lib/squirrelmail/prefs(/.*)? all files system_u:object_r:httpd_squirrelmail_t:s0
/var/lib/stickshift/\.httpd\.d(/.*)? all files system_u:object_r:httpd_config_t:s0
/var/lib/svn(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
/var/lib/trac(/.*)? all files system_u:object_r:httpd_sys_content_t:s0
/var/lib/z-push(/.*)? all files system_u:object_r:httpd_var_lib_t:s0
/var/log/BackupPC(/.*)? all files system_u:object_r:httpd_log_t:s0
/var/log/apache(2)?(/.*)? all files system_u:object_r:httpd_log_t:s0
/var/log/apache-ssl(2)?(/.*)? all files system_u:object_r:httpd_log_t:s0
/var/log/cacti(/.*)? all files system_u:object_r:httpd_log_t:s0
/var/log/cgiwrap\.log.* regular file system_u:object_r:httpd_log_t:s0
/var/log/cherokee(/.*)? all files system_u:object_r:httpd_log_t:s0
/var/log/dirsrv/admin-serv(/.*)? all files system_u:object_r:httpd_log_t:s0
/var/log/glpi(/.*)? all files system_u:object_r:httpd_log_t:s0
/var/log/horizon(/.*)? all files system_u:object_r:httpd_log_t:s0
/var/log/httpd(/.*)? all files system_u:object_r:httpd_log_t:s0
/var/log/lighttpd(/.*)? all files system_u:object_r:httpd_log_t:s0
/var/log/nginx(/.*)? all files system_u:object_r:httpd_log_t:s0
/var/log/php-fpm(/.*)? all files system_u:object_r:httpd_log_t:s0
/var/log/php_errors\.log.* regular file system_u:object_r:httpd_log_t:s0
/var/log/roundcubemail(/.*)? all files system_u:object_r:httpd_log_t:s0
/var/log/suphp\.log.* regular file system_u:object_r:httpd_log_t:s0
/var/log/thttpd\.log.* regular file system_u:object_r:httpd_log_t:s0
/var/log/z-push(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
/var/run/apache.* all files system_u:object_r:httpd_var_run_t:s0
/var/run/cherokee\.pid regular file system_u:object_r:httpd_var_run_t:s0
/var/run/dirsrv/admin-serv.* all files system_u:object_r:httpd_var_run_t:s0
/var/run/gcache_port socket system_u:object_r:httpd_var_run_t:s0
/var/run/httpd.* all files system_u:object_r:httpd_var_run_t:s0
/var/run/lighttpd(/.*)? all files system_u:object_r:httpd_var_run_t:s0
/var/run/mod_.* all files system_u:object_r:httpd_var_run_t:s0
/var/run/nginx.* all files system_u:object_r:httpd_var_run_t:s0
/var/run/php-fpm(/.*)? all files system_u:object_r:httpd_var_run_t:s0
/var/run/piranha-httpd\.pid regular file system_u:object_r:piranha_web_var_run_t:s0
/var/run/thttpd\.pid regular file system_u:object_r:httpd_var_run_t:s0
/var/run/user/apache(/.*)? all files system_u:object_r:httpd_tmp_t:s0
/var/run/wsgi.* socket system_u:object_r:httpd_var_run_t:s0
/var/spool/gosa(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
/var/spool/viewvc(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
/var/www(/.*)? all files system_u:object_r:httpd_sys_content_t:s0
/var/www(/.*)?/logs(/.*)? all files system_u:object_r:httpd_log_t:s0
/var/www/[^/]*/cgi-bin(/.*)? all files system_u:object_r:httpd_sys_script_exec_t:s0
/var/www/cgi-bin(/.*)? all files system_u:object_r:httpd_sys_script_exec_t:s0
/var/www/gallery/albums(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
/var/www/html(/.*)?/sites/default/files(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
/var/www/html(/.*)?/sites/default/settings\.php regular file system_u:object_r:httpd_sys_rw_content_t:s0
/var/www/html(/.*)?/uploads(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
/var/www/html(/.*)?/wp-content(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
/var/www/html/[^/]*/cgi-bin(/.*)? all files system_u:object_r:httpd_sys_script_exec_t:s0
/var/www/html/configuration\.php all files system_u:object_r:httpd_sys_rw_content_t:s0
/var/www/html/owncloud/data(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
/var/www/icons(/.*)? all files system_u:object_r:httpd_sys_content_t:s0
/var/www/miq/vmdb/log(/.*)? all files system_u:object_r:httpd_log_t:s0
/var/www/moodle/data(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
/var/www/moodledata(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
/var/www/openshift/broker/httpd/logs(/.*)? all files system_u:object_r:httpd_log_t:s0
/var/www/openshift/broker/httpd/run(/.*)? all files system_u:object_r:httpd_var_run_t:s0
/var/www/openshift/console/httpd/logs(/.*)? all files system_u:object_r:httpd_log_t:s0
/var/www/openshift/console/httpd/run(/.*)? all files system_u:object_r:httpd_var_run_t:s0
/var/www/openshift/console/log(/.*)? all files system_u:object_r:httpd_log_t:s0
/var/www/openshift/console/tmp(/.*)? all files system_u:object_r:httpd_tmp_t:s0
/var/www/perl(/.*)? all files system_u:object_r:httpd_sys_script_exec_t:s0
/var/www/stickshift/[^/]*/log(/.*)? all files system_u:object_r:httpd_log_t:s0
/var/www/svn(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
/var/www/svn/conf(/.*)? all files system_u:object_r:httpd_sys_content_t:s0
/var/www/svn/hooks(/.*)? all files system_u:object_r:httpd_sys_script_exec_t:s0

 

項目はそれぞれ、『ファイルパス』、『タイプ』、『コンテキスト』です。

 

ここで使用したオプションの fcontext は file-context(ファイルコンテキスト)で、『-l』はリストを表します。

 

結果内容の一つ目の項目は、正規表現で表されます。例えば『/var/www/html/index.html』は『/var/www(/.*)?』にマッチする為、コンテキストは『httpd_sys_content_t』(httpd のコンテンツ)として扱われ、読み込み専用です。また、『httpd_sys_rw_content_t』は httpd の読み書き用コンテンツとして扱われます。

 

※ SELinux の制限は、子孫プロセス(つまり、Apache が起動したプログラム)も対象になります。

※ Apache(httpd) のコンテキストの一覧や説明は『man httpd_selinux』で確認できます。

 

ここで、疑問が生じます。この設定で何故、PHP などが実行できるのでしょうか? また、パスで表す事が出来ないネットワークリソースなどはどうなっているのでしょうか?

 

PHP などは Apache に読み込まれた上に Apache 内部で実行する『許可』があるからですが、ネットワークリソースなども同様に『許可』が与えられています。これら『許可』は『fcontext』ではなく『boolean』で行われています。

 

※ PHP などは Apache 内部で実行されるため、別のプロセスになるワケではありません。

 

では次に、SELinux の『許可』を表す boolean に対する設定を見てみます。

 

# semanage boolean -l | grep -i httpd
httpd_can_network_relay (オフ , オフ) httpd がリレーとして動作することを許可します。
httpd_can_connect_mythtv (オフ , オフ) HTTP デーモンが mythtv に接続することを許可します。
httpd_can_network_connect_db (オフ , オフ) httpd のスクリプトとモジュールがネットワーク経由でデータベースに接続することを許可します。
httpd_use_gpg (オフ , オフ) httpd が gpg を実行することを許可します。
httpd_dbus_sssd (オフ , オフ) Allow Apache to communicate with sssd service via dbus
httpd_enable_cgi (オン , オン) httpd が cgi をサポートすることを許可します
httpd_verify_dns (オフ , オフ) Apache が NS レコードを問い合わせることを許可します。
httpd_dontaudit_search_dirs (オフ , オフ) Dontaudit Apache to search dirs.
httpd_anon_write (オフ , オフ) Apache がパブリックファイル転送サービスに使用されるパブリックファイルを変更することを許可します。ディレクトリおよびファイルのラベルは public_content_rw_t にする必要があります。
httpd_use_cifs (オフ , オフ) httpd が CIFS ファイルシステムにアクセスすることを許可します。
httpd_enable_homedirs (オフ , オフ) httpd がホームディレクトリを読み取ることを許可します。
httpd_unified (オフ , オフ) 全コンテンツファイルの HTTPD 処理を統一します。
httpd_mod_auth_pam (オフ , オフ) Apache が mod_auth_pam を使用することを許可します。
httpd_run_stickshift (オフ , オフ) Apache がパッセンジャーに移行することなく、stickshift モードで実行することを許可します。
httpd_use_fusefs (オフ , オフ) httpd が FUSE ファイルシステムにアクセスすることを許可します。
httpd_can_connect_ldap (オフ , オフ) httpd が LDAP ポートに接続することを許可します。
httpd_can_network_connect (オフ , オフ) httpd のスクリプトとモジュールが TCP を使用するネットワークに接続することを許可します。
httpd_mod_auth_ntlm_winbind (オフ , オフ) Apache が mod_auth_ntlm_winbind を使用することを許可します。
httpd_use_sasl (オフ , オフ) httpd が SASL に接続することを許可します。
httpd_tty_comm (オフ , オフ) ターミナルとの通信のため HTTPD を統一します。 ターミナルで証明書のパスフレーズを入力する際に必要になります。
httpd_sys_script_anon_write (オフ , オフ) Apache スクリプトがパブリックコンテンツに書き込むことを許可します。ディレクトリとファイルのラベルは public_rw_content_t にする必要があります。
httpd_graceful_shutdown (オン , オン) HTTPD が正しくシャットダウンするよう 80 番ポートに接続することを許可します。
httpd_can_connect_ftp (オフ , オフ) httpd が FTP ポートと一時ポートに接続する FTP クライアントとして動作することを許可します。
httpd_read_user_content (オフ , オフ) httpd がユーザーのコンテンツを読み取ることを許可します。
httpd_use_nfs (オフ , オフ) httpd が NFS ファイルシステムにアクセスすることを許可します。
httpd_can_connect_zabbix (オフ , オフ) HTTP デーモンが Zabbix に接続することを許可します。
httpd_tmp_exec (オフ , オフ) Apache が tmp の内容を実行することを許可します。
httpd_run_preupgrade (オフ , オフ) Allow Apache to run preupgrade
httpd_manage_ipa (オフ , オフ) httpd プロセスが IPA コンテンツを管理することを許可します。
httpd_can_sendmail (オフ , オフ) HTTP デーモンがメールを送信することを許可します。
httpd_builtin_scripting (オン , オン) httpd が組み込みスクリプト (一般的に PHP) を使用することを許可します。
httpd_dbus_avahi (オフ , オフ) Apache が dbus 経由で avahi サービスと通信することを許可します。
httpd_can_check_spam (オフ , オフ) httpd デーモンが迷惑メールをチェックすることを許可します。
httpd_can_network_memcache (オフ , オフ) httpd が memcache サーバーに接続することを許可します。
httpd_can_network_connect_cobbler (オフ , オフ) https のスクリプトとモジュールがネットワーク経由で cobbler に接続することを許可します。
httpd_serve_cobbler_files (オフ , オフ) HTTPD のスクリプトとモジュールが cobbler ファイルを処理することを許可します。
awstats_purge_apache_log_files (オフ , オフ) awstats が httpd ログファイルをパージできるかどうかを指定します。
httpd_execmem (オフ , オフ) httpd のスクリプトとモジュールが execmem/execstack を実行することを許可します。
httpd_ssi_exec (オフ , オフ) HTTPD がシステム CGI スクリプトと同じドメイン内で SSI 実行ファイルを実行することを許可します。
httpd_use_openstack (オフ , オフ) httpd が OpenStack ポートにアクセスすることを許可します。
httpd_enable_ftp_server (オフ , オフ) httpd が FTP ポートをリッスンして FTP サーバーとして動作することを許可します。
httpd_setrlimit (オフ , オフ) httpd デーモンがリソースの制限を変更することを許可します。

 

項目はそれぞれ、『コンテキスト』、『(状態,初期値)』、『説明』です。

 

先程の PHP の問題は、『httpd_builtin_scripting』が『オン』に設定されいる為に、問題無く実行するが出来ます。また、『httpd_can_network_connect』はスクリプトなどでの通信に影響しますが、SMTP や IMAP サーバーへの接続では、『httpd_can_sendmail』に影響されます。

 

その他で Apache に影響する設定として、ポート番号があります。

 

今度は、SELinux のポート番号に対する設定を見てみます。

 

# semanage port -l | grep http
http_cache_port_t tcp 8080, 8118, 8123, 10001-10010
http_cache_port_t udp 3130
http_port_t tcp 80, 81, 443, 488, 8008, 8009, 8443, 9000
pegasus_http_port_t tcp 5988
pegasus_https_port_t tcp 5989

 

項目はそれぞれ、『SELinux ポートタイプ』、『TCP/DUP』、『ポート番号』です。

 

ここでは、例えば『http_port_t』のように、『httpd』ではなく『http』である事に注意して下さい。コレは、デーモンに対する設定ではなく、プロトコルに対する設定である為です。

 

つまり、例えばこの『http_port_t』を変更した場合は、Apache だけではなく、HTTP を利用する他のデーモンなどにも影響しますので、通常は変更しない方が懸命です。

 

 

SELinux の設定を変更する

SELinux の設定を変更する簡単な方法は『semanage』を利用する方法です。

 

先ずは、fcontext の変更から見ていきます。

 

例えば『/var/www/test』を作成し、Apache から書き込み可能にする場合。

 

# # ディレクトリの作成
# mkdir /var/www/test
#
# # 所有権の変更
# chown apache /var/www/test
# chgrp apache /var/www/test
#
# # SELinux に許可を与える。
# semanage fcontext -a -t httpd_sys_rw_content_t '/var/www/test(/.*)?'
#
# # SELinux の権限を変更する。
# restorecon /var/www/test

 

既に『/var/www/test』が存在し、Apache から書き込み可能にする場合。

 

# # 所有権の変更
# chown -R apache /var/www/test
# chgrp -R apache /var/www/test
#
# # SELinux に許可を与える。
# semanage fcontext -a -t httpd_sys_rw_content_t '/var/www/test(/.*)?'
#
# # 既に存在するファイル全てに対して SELinux の権限を変更する。
# restorecon -R /var/www/test

 

ここで注意すべき事は、『-a』オプションは、許可リストのへの追加であり、ファイルの権限変更ではない事です。そして『-t』でコンテキストを、最後の引数は、パスにマッチする正規表現を指定します。また、許可リストはファイルとして記録される為、再起動後も有効です。

 

『restorecon』コマンドは、許可リストに合わせてファイルのコンテキストも変更します。また、『-R』オプションは『再帰的』を意味するモノですので、ディレクトリ配下の全てのファイル/ディレクトリが対象になります。

 

また、『chown』や『chgrp』でファイルの所有者とグループを『apache』に変更していますが、コレはファイルパーミッション対策です。

 

カーネルはファイルやディレクトリの作成時、パスにマッチするファイルコンテキストが存在する場合には、自動でコンテキストの設定を行います。つまり、『cp』コマンドなどではコンテキストの設定が行われますが、同一デバイス内からの『mv』コマンドなどによる移動では、コンテキストの設定は行われないので注意して下さい。

 

この他にも、通常は絶対にやってはいけない設定ですが Apache を SELinux による制限の無いデーモンにする方法もあります。

 

# semanage fcontext -a -t unconfined_exec_t /usr/sbin/httpd

 

この方法は、Apache を unconfined(制限されない)存在にする反面、SELinux による保護も失います。Apache のセキュリティ設定を正しく行う知識がない場合は、自殺行為ですので絶対にやってはいけません。

 

※ 詳細な fcontext の設定は、『man semanage-fcontext』で確認して下さい。
※ 使い方:『semanage fcontext (-a : 追加[Add] -m 変更[Modify] -d 削除[Delete]) -t タイプ[Type] ファイルコンテキスト パス』

 

 

 

今度は『boolean』の設定を見てみます。

 

例えば SMTP サーバーに直接接続してメールを送信できるようにする場合。(条件を簡単にする為に、アウトバンドなしの同一サーバー内とします)

 

# semanage boolean -m --on httpd_can_sendmail

 

※  使い方:『semanage boolean -m 変更[Modify] (–on/–off) コンテキスト』

 

この時、『httpd_can_sendmail』には SMTP (ポート番号:25)に接続する権限も含まれていますので、『httpd_can_network_connect』を ON にする必要はありません。

 

ここで、もう一度 SELinux がホワイトリスト形式である事を思い出して下さい。

SELinux の許可フロー

ホワイトリスト形式では、条件に合ったモノが見つかった段階で『許可』になります。チェックする順番は定かではありませんが、『httpd_can_network_connect』にした場合、その他の通信も許可されますので、その分、セキュリティー強度が低下します。では次に、『fcontext』と『boolean』の設定が同時に必要なケースを見ていきます。例えば、複数のデーモンから同一ファイルにアクセスする為にはどのようにすれば良い似でしょうか?一番簡単な方法は、パブリックコンテンツにする方法です。『public_content_t』と『public_rw_content_t』というファイルコンテキストが存在するので、これを利用するのが簡単です。パブリックコンテンツは通常、読み込みアクセスには制限がありませんが、書き込みには『boolean』による制限が与えられています。Apache の場合は『httpd_anon_write』と『httpd_sys_script_anon_write』が該当します。『httpd_anon_write』は Apahce プロセスによる書き込み、『httpd_sys_script_anon_write』は、CGI スクリプトなどの子孫プロセスが該当します。また、Apache 以外のデーモンでも同様の『boolean』が存在するハズですので、そちらの変更も忘れない様にして下さい。また、複数のデーモンによるファイルアクセスには、当然ですが、ファイルパーミッションも影響してきます。『chmod』コマンドなどを使い、適切なファイルパーミッションを与える様にして下さい。 

次は『port』の設定を見てみます。

 

例えば HTTP プロトコルに使用するポートに 9999 番を追加してみます。

 

# semanage port -a -t http_port_t -p tcp 9999

 

この操作は、HTTP プロトコルにポート番号を追加する行為なので、Apache 以外にも Nginx など、HTTP プロトコルを利用するデーモンに影響します。

 

SELinux のテストと実装

SELinux には、『semanage』だけではなく、一時的に設定を変更できるツールも幾つか存在します。

 

# # 『/var/www/test/file1』ファイルのコンテキストを『httpd_sys_rw_content_t』に変更する。
# chcon -t httpd_sys_rw_content_t /var/www/test/file1
#
# # 『/var/www/test/』ディレクトリと配下のファイルコンテキストを再帰的に『httpd_sys_rw_content_t』に変更する。
# chcon -R -t httpd_sys_rw_content_t /var/www/test/
#
# # コンテキストを元に戻す。
# restorecon -R /var/www/test/

 

『chcon』はファイルのコンテキストを直接変更するコマンドで、『restorecon』コマンドを用いてデフォルトの状態に戻すことができます。永続的な変更には、『semanage』を使うべきですが、テストなどの一時的な変更には適しています。

# # httpd_can_sendmail を ON にします。
# setsebool httpd_can_sendmail=on
#
# # httpd_can_sendmail を OFF にします。
# setsebool httpd_can_sendmail=off

 

『setsebool』は『boolean』を一時的に変更するコマンドで、再起動後には失われてしまいます。永続的な変更には、『semanage』を使うべきですが、テストなどの一時的な変更には適しています。

 

# # SELinux によって発生した拒否を確認する
# aureport -a

 

『aureport』は『拒否』を確認するには便利なツールです。詳しくはコチラをご覧下さい。

GUI で SELinux を設定する

SELinux には system-config-selinux という GUI ツールが存在します。

 

次のコマンドでインストールします。(パッケージ名:policycoreutils-gui)

 

# dnf install policycoreutils-gui

 

GUI メニューからでも起動できるハズですが、失敗することも多いので、コマンドラインから起動します。

 

$ system-config-selinux &

 

SELinux の GUI ツール

 

このツールでは、SELinux の ON / OFF や『ファイルのラベル付け』(ファイルコンテキストの設定)、『論理値』(boolean)の設定などが行えます。

  • 『システムデフォルトの強制モード』 … システム起動時の SELinux のモード。『強制』は SELinux が有効、『容認』は SELinux が干渉しない状態、『無効』は SELinux が完全に機能しない状態。
  • 『現在の強制モード』 … 現在の SELinux のモード。『強制』は SELinux が有効、『容認』は SELinux が干渉しない状態。
  • 『システムデフォルトのポリシータイプ』 … 通常は『tageted』のみ。SELinux の設定の組み合わせで、作成されている場合のみ選択可能。

 

SELinux 論理値設定 GUI

 

『論理値』(boolean)の設定では、チェックしたものが ON になります。また、デーモン名が『httpd』ではなく『apache』になっている事に注意して下さい。

 

SELinux ファイルコンテキストの設定 GUI

 

追加ボタンを押すと、次のダイアログが表示されます。

 

SELinux ファイルコンテキストの追加 GUI

 

  • 『ファイルの仕様』 … ファイルパスを表す正規表現。
  • 『ファイルのタイプ』 … 必要に応じて指定して下さい。特に指定したくない場合は、『全ファイル』で問題ありません。
  • 『SELinux のタイプ』 … ファイルコンテキストを指定して下さい。
  • 『MLS』 … レベル指定です。通常は『s0』で問題ありません。

 

SELinux ネットワークポート設定 GUI

 

追加ボタンを押すと、次のダイアログが表示されます。

 

SELinux ポート番号追加 GUI

 

  • 『ポート番号』 … 番号かまたは、「開始番号-終了番号」でポート番号を指定して下さい。
  • 『プロトコル』 … 『tcp』または『udp』を指定して下さい。
  • 『SELinux のタイプ』 … コンテキストを指定して下さい。(例:http_port_t)
  • 『MLS/MCS レベル』 … レベル指定です。通常は『s0』で問題ありません。

 

その他の設定は、通常はあまり使用しません。

 

 

 

SELinux を一時的に無効にする

SELinux を全て無効にする方法は次のとおりです。

# setenforce 0

SELinux を全て有効にする方法は次のとおりです。

# setenforce 1

現在の SELinux 状態を取得する方法は次のとおりです。

$ getenforce

 

 

 

ポリシーモジュールを追加する

上記の方法では解決できない場合に限り、ポリシーモジュールで対応する方法があります。

# aureport -a
125236. 2017年11月20日 13:56:45 php-fpm system_u:system_r:httpd_t:s0 0 file map system_u:object_r:httpd_sys_rw_content_t:s0 denied 12365
# ausearch -c 'php-fpm' --raw | audit2allow -M my-phpfpm
# semodule -X 300 -i my-phpfpm.pp

 

この方法は、最終手段に近いため、多用するのは止めておきましょう。