クラウドインテグレーション部の渡邊です。
本記事のシリーズでは、サーバの構築・運用に最低限必要なセキュリティの体系的知識習得を目的としています。
本シリーズの全体像と今回執筆の内容の位置づけは以下の通りです。
今回は、パーミッション、ACL、SELinuxの話をします。
Amazon Linux 2
パーミッションとは、ファイルやディレクトリに設定されているアクセス権限のことです。
権限は以下のパーミッションの下表の通り3種類あります。
また、パーミッションは数値または記号で表記することができます。
ユーザ種別として所有者・グループ・その他ユーザーがあり各種別に対してアクセス権限が付与されます。
アクセス権 | 記号 | 数字 | ファイル | ディレクトリ |
---|---|---|---|---|
読み込み | r (Read) | 4 | ファイルの内容表示が可能 | ディレクトリ内のディレクトリ、ファイル表示が可能 |
書き込み | w (Write) | 2 | ファイルへの書き込み・削除等が可能 | ディレクトリ内にディレクトリ、ファイルを作成、削除等が可能 |
実行 | x(eXecute) | 1 | ファイルの実行が可能 | ディレクトリへのアクセスが可能 |
ディレクトリ配下のファイルを閲覧する際に、親ディレクトリの実行権限がないことで見れなくなることもあるので、権限設定の際は気をつけてください。
ディレクトリやファイルの権限はls -l
コマンドで確認できます。
$ ls -l
drwxrwxrw- 3 ec2-user ec2-user 126 8月 16 07:13 ec2-user
左側にdrwxrwxrw-
(数値表記:776)とありますが、こちらは各ユーザ種別に対するアクセス権限が記号で表記されています。 各項目の内容は下表の通りです。なお-
は権限がないことを表します。
d | r | w | x | r | w | x | r | w | x |
---|---|---|---|---|---|---|---|---|---|
ディレクトリ | 読み | 書き | 実行 | 読み | 書き | 実行 | 読み | 書き | 実行 |
所有者 | グループ | その他ユーザ |
よってdrwxrwxrw-
の場合は以下の権限がec2-user
というディレクトリに対して付与されていることになります。
実行権限に関する特殊なパーミッションが3つあります。
下表の表示例を見てみましょう。
例えばSUIDの表示例では所有者の実行権限を表す部分がs
と表記されています。
このように、各特殊なパーミッションで実行権限の記号がx
ではなくt
またはs
と表記されています。
パーミッション | できることや制限 | 設定方法 | 表示例 (記号(数値)) |
---|---|---|---|
SUID | 実行権限があるユーザが所有者権限で実行 | chmodコマンドでu+sまたは元のパーミッションに4000を足した数値を設定 | rws r-x r-x(4755) |
SGID | 実行権限があるユーザがグループ権限で実行 | chmodコマンドでg+sまたは元のパーミッションに2000を足した数値を設定 | rwx r-s r-x(2755) |
スティッキービット | その他のユーザによる削除とリネームを制限 | chmodコマンドでo+tまたは1000を足して設定 | rwx r-x r-t (1755) |
スティッキビットは一部のディレクトリ(/tmpや/var/tmpなど)にデフォルトで設定されています。
$ ls -l/ | grep tmp
drwxrwxrwt 8 root root 261 8月 16 11:03 tmp
SUIDやSGIDにはその性質からセキュリティに問題が発生する可能性があるので注意して設定しましょう。以下の例では本来アクセスする権限のないその他のユーザtest-user
がSUIDを利用することでアクセスに成功してしまう例です。
# SUIDがまだ設定されていないことを確認
[root@ip-10-23-0-175 ~]# ls -l `which touch`
-rwxr-xr-x 1 root root 58264 Jan 23 2020 /usr/bin/touch
# touchコマンドファイルにsuidを付与(touchコマンドの実行ファイルのパスに対して許可している)
[root@ip-10-23-0-175 ~]# chmod u+s `which touch`
# touchコマンドファイルにsuidが付与されたことを確認(-rwsr-xr-xになっている)
[root@ip-10-23-0-175 ~]# ls -l `which touch`
-rwsr-xr-x 1 root root 58264 Jan 23 2020 /usr/bin/touch
[root@ip-10-23-0-175 ~]# su - test-user
Last login: Wed Aug 16 06:25:17 UTC 2023 on pts/0
# 作成先のディレクトリ(root)の権限を確認(dr-xr-x---)
[test-user@ip-10-23-0-175 ~]$ ls -l -d /root
dr-xr-x--- 3 root root 183 Aug 16 11:49 /root
ではtest-user
で動作確認してみます。
# txtファイルの作成に成功する
[test-user@ip-10-23-0-175 ~]$ touch /root/suid_test.txt
#test-userが作成したファイルが確認できない
[test-user@ip-10-23-0-175 ~]$ ls -l /root/suid_test.txt
ls: cannot access /root/suid_test.txt: Permission denied
その他のユーザは親ディレクトリroot
の権限が与えられていませんが、touch
コマンドの実行ファイルの所有者であるroot
ユーザとして実行されたため作成に成功してしまいました。
作成されたファイルを確認してみると、test-user
が作成したファイルの所有者がroot
になっています。
[test-user@ip-10-23-0-175 ~]$ exit
logout
[root@ip-10-23-0-175 ~]# ls -l /root/suid_test.txt
-rw-r--r-- 1 root test-user 0 Aug 16 11:49 /root/suid_test.txt
ACLはパーミッションと比べ細やかにアクセス権限を設定できる機能です。
任意アクセス制御(DAC)というアクセス制御モデルでパーミッションのように自身の管理下にあるリソースへのアクセス制御を自身が決定できます。
基本的なコマンドは以下の通りです。
変更方法に記載のACLエントリは、タグ種類:タグ修飾子:パーミッションの形式で指定します。
タグ種類は以下の2種類に分類され、それぞれ下表のように表現します。
ACLエントリ(基本ACL) | ACLエントリ設定例 | 意味 |
---|---|---|
u[ser]::perms | u::rw | 従来パーミッションの owner に相当 |
g[roup]::perms | g::r | 従来パーミッションの group に相当 |
o[ther]:perms | o::- | 従来パーミッションの other に相当 |
ACLエントリ(拡張ACL) | ACLエントリ設定例 | 意味 |
---|---|---|
u[ser]:uid:perms | u:annabel:rw | エントリのパーミッションをタグ修飾子に指定されたユーザへ適用 ※uidはユーザ名を指定しても良い |
g[roup]:gid:perms | g:teach:rw | エントリのパーミッションをタグ修飾子に指定されたグループへ適用 ※gidはグループ名を指定しても良い |
m[ask]::perms | m::rw | グループや所有者を除くユーザ で設定されている権限の最大値 |
なお、基本ACLと拡張ACLは両立することが可能で、まとめて設定することができます。
実際に見てみましょう。
事前にユーザuser1
とuser2
、テスト用のファイルacl_test.txt
を作成しています。
[root@ip-10-23-0-175 ec2-user]# cat /tmp/acl_test.txt
hello world
[root@ip-10-23-0-175 ec2-user]# getfacl /tmp/acl_test.txt
getfacl: Removing leading '/' from absolute path names
# file: tmp/acl_test.txt
# owner: root
# group: root
user::rw-
group::r--
other::r--
ユーザごとに権限を付与するために設定や動作確認をしてみます。細かい制御をしたい場合はこのようにユーザごとに制御できることを覚えておきましょう。
[root@ip-10-23-0-175 ec2-user]# su - user1
# user1はこの時点ではまだ書き込めない
[user1@ip-10-23-0-175 ~]$ echo "goodbye world" > /tmp/acl_test.txt
-bash: /tmp/acl_test.txt: Permission denied
[user1@ip-10-23-0-175 ~]$ exit
logout
# acl_test.txtにuser1が書き込み読み込みできる権限を追加
[root@ip-10-23-0-175 ec2-user]# setfacl -m u:user1:rw /tmp/acl_test.txt
[root@ip-10-23-0-175 ec2-user]# getfacl /tmp/acl_test.txt
getfacl: Removing leading '/' from absolute path names
# file: tmp/acl_test.txt
# owner: root
# group: root
user::rw-
user:user1:rw-
group::r--
mask::rw-
other::r--
# 読み書きができるようになっているか動作確認
[root@ip-10-23-0-175 ec2-user]# su - user1
最終ログイン: 2023/08/16 (水) 12:51:42 UTC日時 pts/0
[user1@ip-10-23-0-175 ~]$ cat /tmp/acl_test.txt
goodbye world
[user1@ip-10-23-0-175 ~]$ echo "goodbye world" > /tmp/acl_test.txt
[user1@ip-10-23-0-175 ~]$ cat /tmp/acl_test.txt
goodbye world
[user1@ip-10-23-0-175 ~]$ exit
logout
# 拡張ACLによって許可されていないユーザは権限がないため失敗する
[root@ip-10-23-0-175 ec2-user]# su - user2
[user2@ip-10-23-0-175 ~]$ cat /tmp/acl_test.txt
goodbye world
[user2@ip-10-23-0-175 ~]$ echo "world" > /tmp/acl_test.txt
-bash: /tmp/acl_test.txt: Permission denied
SELinux(Security-Enhanced Linux)はACLとは異なり強制アクセス制御(MAC)という唯一のルール定義者がアクセス制御のルールを決定するモデルをとっています。
SELinux には以下 3 つの動作モードがあります。
動作モード | SELinux | 機能 |
---|---|---|
enforcing | 有効 | アクセス制御が有効 |
permissive | 有効 | アクセス制御は無効だが警告メッセージを表示 |
disable | 無効 | - |
このモデルの特性からroot
ユーザも制御されるとても強い制御なのでソフトウェアベンダー側がセットアップのマニュアルで無効にする手順が含まれていることもあります。
SELinuxがenforcingで動作上に問題がある場合は原因の切り分けを行うために、動作モードをpermissive
にします。もし動作が改善したらSELinuxが原因ということになります。
基本的なコマンドは以下の通りです。
/etc/selinux/config
のSELINUXの値(例:SELINUX=enforcing)を書き換え、OSを再起動してください。
アクセス制御はセキュリティ・コンテキストというラベル付けされた情報をもとに行っています。
ラベル付けされた情報はSELinuxユーザ: SELinuxユーザが認可されたロール:SELinuxがアクセスするタイプ:セキュリティレベルの4種類の要素で構成されています。
例:root:staff_r :staff_t :s0-s0:c0.c1023
SELinuxの機能がいくつかありますが、代表的な2つを紹介します。
・TE(Type Enforcement):プロセスがリソースにアクセスする権限を制御する機能
TEではセキュリティポリシーを確認してリソースにアクセスします。
例えば、httpd_t
タイプはhttpd_sys_content_t
のタイプに該当するリソースにアクセスを許可するというポリシーが含まれています。
・RBAC(Role Based Access Control):ロールと呼ばれる役割に応じたアクセス権をユーザに付与することでアクセス制御を行う機能
その範囲内ならユーザがアクセスを制御することも可能であることからその点でDACとMACの中間的なモデルと言われることもあります。
引用元:「RBAC in SELinux」 Gentoo Linux
実際にTEによるapacheのプロセス制御を見てみましょう。
まず、apacheの動作を確認していきます。
DocumentRootの設定を変更することでコンテンツを表示するパスを変更できます。/var/www/html
を/var/www2/html
へ変更することで表示する内容を変更しました
# index.htmlに書き込みHelloが表示されることを確認
[root@ip-10-23-0-175 ec2-user]# systemctl start httpd
[root@ip-10-23-0-175 ec2-user]# echo "Hello" > /var/www/html/index.html
[root@ip-10-23-0-175 ec2-user]# curl http://localhost/index.html
Hello
[root@ip-10-23-0-175 ec2-user]# systemctl restart httpd
[root@ip-10-23-0-175 ec2-user]# mkdir -p /var/www2/html
[root@ip-10-23-0-175 ec2-user]# echo "Hello2" > /var/www2/html/index.html
# 下記3行の「www」を「www2」に変更する
# 変更前:
# DocumentRoot "/var/www/html"
# <Directory "/var/www">
# <Directory "/var/www/html">
# 変更後:
# DocumentRoot "/var/www2/html"
# <Directory "/var/www2">
# <Directory "/var/www2/html">
[root@ip-10-23-0-175 ec2-user]# vi /etc/httpd/conf/httpd.conf
[root@ip-10-23-0-175 ec2-user]# systemctl restart httpd
[root@ip-10-23-0-175 ec2-user]# curl http://localhost/index.html
Hello2
SELinuxを設定していきます。
OSによりますが、初期状態が基本的にはDisabledかPermissiveであるためEnforcingに変更します。
# SELinuxの状態がDisabledになっていた
[root@ip-10-23-0-175 ec2-user]# getenforce
Disabled
# SELINUX=permissiveに書き換える
[ec2-user@ip-10-23-0-175 ~]$ sudo vi /etc/sysconfig/selinux
[root@ip-10-23-0-175 ec2-user]# sudo reboot
# 一時的にEnforcingにする(Disabledの状態では不可、Permissiveの状態での実行が必要)
[root@ip-10-23-0-175 ec2-user]# setenforce 1
# SELinuxの状態がEnforcingになっていることを確認
[root@ip-10-23-0-175 ec2-user]# getenforce
Enforcing
この状態で作成した/var/www2/html/index.html
の内容をapacheで表示を試みると失敗します。
# Hello2が表示されず、403エラーになることを確認
[root@ip-10-23-0-175 ec2-user]# systemctl start httpd
[root@ip-10-23-0-175 ec2-user]# 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 this resource.</p>
</body></html>
新規で作られたファイルはapacheがアクセスできるコンテキストのタイプではないためアクセスに失敗しました。
あるタイプのプロセスが、どのタイプのリソースにアクセスできるかはポリシーで制御されております。
ポリシー、プロセス、ファイルを確認してみるとapacheは/var/www2/html/index.html
にアクセスできないことがわかります。
なぜなら、apacheのプロセスは/var/www2/html/index.html
のタイプvar_t
にアクセスすることがポリシーで許可されていないためです。
なお、セキュリティコンテキストを確認するにはコマンドに-Z
オプションを付けます。
# ポリシー設定の確認(httpd_sys_content_tは許可、var_tは許可なし)
$ sudo sesearch -AC -s httpd_t -t httpd_sys_content_t -c file | grep httpd_sys_content_t
allow httpd_t httpd_sys_content_t : file { ioctl read getattr lock open } ;
[ec2-user@ip-10-23-0-175 ~]$ sudo sesearch -AC -s httpd_t -t var_t -c file
# httpd プロセスの確認
[root@ip-10-23-0-175 ec2-user]# ps -efZ | grep httpd
system_u:system_r:httpd_t:s0 root 3292 1 0 14:27 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 apache 3293 3292 0 14:27 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 apache 3294 3292 0 14:27 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 apache 3295 3292 0 14:27 ? 00:00:00 /usr/sbin/httpd -cDFOREGROUND
system_u:system_r:httpd_t:s0 apache 3296 3292 0 14:27 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 apache 3297 3292 0 14:27 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 root 3341 3272 0 14:28 pts/0 00:00:00 grep --color=auto httpd
# SELinuxコンテキストの確認
[root@ip-10-23-0-175 ec2-user]# ls -ldZ /var/www*
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 /var/www
drwxr-xr-x. root root system_u:object_r:var_t:s0 /var/www2
ポリシー通りのアクセスを成功させるために、新規作成したファイルおよびディレクトリのタイプを変更をします。
# SELinuxコンテキストの変更
[root@ip-10-23-0-175 ec2-user]# chcon -R -t httpd_sys_content_t /var/www2
# /var/www2のSELinuxコンテキストが「system_u:object_r:httpd_sys_content_t:s0」になっていることを確認
[root@ip-10-23-0-175 ec2-user]# ls -ldZ /var/www*
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 /var/www
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 /var/www2
# Hello2が表示されることを確認
[root@ip-10-23-0-175 ec2-user]# curl http://localhost/index.html
Hello2
apacheにアクセスさせたいファイル及びディレクトリのコンテキストを変更することで、ポリシー通りにアクセスできることが確認できました。
今回は権限の制御で以下を説明しました。
次回の記事では暗号化について執筆予定です。ぜひそちらも御覧ください!
【参考】