SELinux を使おう．使ってくれ．

# この記事の目的
SELinux って邪魔者ですか？

「トラブルシュートの時に邪魔だから」「トラブルの元だから」とか言う理由で `/etc/selinux/config` で `SELINUX=disable` したり `setenforce 0` したりしていませんか？

SELinux は理解さえすればとても簡単です．

本番環境でファイアウォールと WAF の設定をして満足していないで SELinux を使いましょう．

## 対象

SELinux を初めて触る人向けです．

玄人の方は他へ．．．

## 本稿の範囲
本稿では SELinux を導入しておしまいです．あくまで「みんな，簡単だからね，使おうね！」と言いたいのです．

本当は SELinux の効果を示すために Exploit を仕込んだアプリケーションから root を取って不正にファイルに触るところまでやりたいのですが，これまた別の記事にします．

僕の願いは Linux インストール直後に /etc/selinux/config の中身を disabled にしないで欲しい，それだけです．

細かいチューニングなども書き始めると終わらないので，後日別の記事で書きます．

# セットアップ
## Debian Jessie の場合
メンテナンスが行き届いておらず，今から SELinux を使い始めるにはそう容易ではありません．
万人受けするデフォルトのポリシを提供しているパッケージ（selinux-policy-default など）が apt レポジトリから削除されているためです．

自身でポリシを定義すれば使えますが難易度が高くなるため今回は Debian はやめます．

## CentOS 7
そこでみんな大好き CentOS です．

```
# yum -y install selinux-policy-targeted setools
```

インストールが終わったらリブートします．

リブート後，SELinux の動作モード（Disabled / Enforcing / Permissive）を表示する `getenforce` コマンドを叩いてみます．

```
# getenforce
Enforcing
```

# SELinux の動作モード
Disabled / Permissive / Enforcing の 3 モードがあります．

Disabled と Permissive / Enforcing の切り替えは `/etc/selinux/config` ファイルで行います．
Permissive と Enforcing の一時的な切り替えは `setenforce` コマンドを使います．

いずれも恒久的にモードを固定する場合は `/etc/selinux/config` を書き換えます．

## Disabled
SELinux が適用されていない状態．監査ログも残らないしリソースへのアクセスも自由にできます．


## Permissive
SELinux は適用されているがアクセス制御が実行されない．ポリシに違反するアクセスは監査ログに記録されます．
SELinux のチューニングに使います．

## Enforcing
SELinux が適用され，アクセス制御が有効になっている状態．
後述のチューニングを終え運用状態に移行したらこのモードにします．

ポリシに違反するアクセスは全て遮断されます．

# SELinux が有効になるとどうなるか

Apache で試しましょう．
まずは DocumentRoot となっている `/var/www/html` に `index.html` を作ってみます．

```
# cd /var/www/html
# vi index.html
# cat index.html
hogehoge
```

ブラウザで見てみます．

```
# curl http://localhost/
hogehoge
```

次に `/tmp/index.html` を作って `/var/www/html` にコピーしてきます．

```
# vi /tmp/index.html
# cat /tmp/index.html
foobar
# cp -a /tmp/index.html /var/www/html/
cp: `/var/www/html/index.html' を上書きしますか? yes
```

再び HTTP で GET してみます．

```
# curl http://localhost/
<!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>
```

403 が出ました．

# なぜ 403 になったのか

監査ログを見てみます．

```
# ausearch -m avc
（中略）
time->Wed Dec 21 08:41:26 2016
type=SYSCALL msg=audit(1482277286.335:911): arch=c000003e syscall=2 success=no exit=-13 a0=7f7c21930280 a1=80000 a2=0 a3=4 items=0 ppid=2385 pid=2390 auid=4294967295 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) ses=4294967295 comm="httpd" exe="/usr/sbin/httpd" subj=system_u:system_r:httpd_t:s0 key=(null)
type=AVC msg=audit(1482277286.335:911): avc:  denied  { open } for  pid=2390 comm="httpd" path="/var/www/html/index.html" dev="dm-0" ino=416303 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:user_tmp_t:s0 tclass=file
```

system_u:system_r:httpd_t で unconfined_u:object_r:user_tmp_t のファイルにアクセスできなかったようです．

```
# ls -laZ /var/www/html
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 .
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 ..
-rw-r--r--. root root unconfined_u:object_r:user_tmp_t:s0 index.html
```

Apache（httpd）が `/var/www/*` 以下で公開するファイルは httpd_sys_content_t が付与されていなければならないことが分かります．

```
# grep -R '/var/www' /etc/selinux/targeted/
（中略）
/etc/selinux/targeted/active/file_contexts:/var/www(/.*)?       system_u:object_r:httpd_sys_content_t:s0
```

## タイプを是正する
`chcon` で個別に設定することも可能ですが，`/var/www` などの既定のディレクトリはシステム標準でテンプレートが用意されています．
この場合は `restorecon` コマンドを使って簡単に是正することが可能です．

```
# ls -alZ /var/www/html
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 .
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 ..
-rw-r--r--. root root unconfined_u:object_r:user_tmp_t:s0 index.html
# restorecon -RF /var/www/html/
# ls -alZ /var/www/html
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 .
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 ..
-rw-r--r--. root root system_u:object_r:httpd_sys_content_t:s0 index.html
```

今度は正しくアクセスできるはずです．

```
# curl http://localhost/
foobar
```

# SELinux 簡単でしょ？ それなのに便利でしょ？
SELinux が有効になっているとパーミッションが取れたとしてもファイルの内容にアクセスできないようになります．

これはセキュリティホールを突かれてもシステムファイルを容易には読めない，容易には書き換えられないことを示しています．

トラブルシュートが難しい？
監査ログ見れば原因はすぐに分かります．何も難しいことはありません．
むしろ侵入されてぱっと見の足跡が残らないように荒らされるよりは随分とマシってもんです．

次回以降の記事で，root を取って中に入っても自由にファイルを読みに行けないことを実証していきます．

関連記事：
[Apache における SELinux の効果](http://qiita.com/chi9rin/items/0e97fb4d500a28001781)