Linux × Security 権限の制御編

    Linux × Security 権限の制御編

    目次

      はじめに

      クラウドインテグレーション部の渡邊です。

      本記事のシリーズでは、サーバの構築・運用に最低限必要なセキュリティの体系的知識習得を目的としています。

      本シリーズの全体像と今回執筆の内容の位置づけは以下の通りです。

      今回は、パーミッション、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

      ACLはパーミッションと比べ細やかにアクセス権限を設定できる機能です。
      任意アクセス制御(DAC)というアクセス制御モデルでパーミッションのように自身の管理下にあるリソースへのアクセス制御を自身が決定できます。
      基本的なコマンドは以下の通りです。

      • 表示方法
        • getfacl [オプション] ファイル名
      • 変更方法
        • setfacl [-mまたは-x] [ACLエントリ],[ACLエントリ],[ACLエントリ] ファイル名

      変更方法に記載のACLエントリは、タグ種類:タグ修飾子:パーミッションの形式で指定します。

      タグ種類は以下の2種類に分類され、それぞれ下表のように表現します。

      • 基本ACL:通常のパーミッションに相当
      • 拡張ACL:特定のユーザに対するパーミッションなどを追加で設定
      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は両立することが可能で、まとめて設定することができます。
      実際に見てみましょう。
      事前にユーザuser1user2、テスト用のファイル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

      SELinux(Security-Enhanced Linux)はACLとは異なり強制アクセス制御(MAC)という唯一のルール定義者がアクセス制御のルールを決定するモデルをとっています。

      SELinux には以下 3 つの動作モードがあります。

      動作モード SELinux 機能
      enforcing 有効 アクセス制御が有効
      permissive 有効 アクセス制御は無効だが警告メッセージを表示
      disable 無効 -

      このモデルの特性からrootユーザも制御されるとても強い制御なのでソフトウェアベンダー側がセットアップのマニュアルで無効にする手順が含まれていることもあります。

      SELinuxがenforcingで動作上に問題がある場合は原因の切り分けを行うために、動作モードをpermissiveにします。もし動作が改善したらSELinuxが原因ということになります。

      基本的なコマンドは以下の通りです。

      • SELinuxの状態を確認するコマンド:getenforce
        • getfacl [オプション] ファイル名
      • 設定変更コマンド(一時的)
        • EnforcingモードからPermissiveモード:setenforce 0
        • PermissiveモードからEnforcingモード:setenforce 1
        • 設定変更を永続的に適用するためには、/etc/selinux/configのSELINUXの値(例:SELINUX=enforcing)を書き換え、OSを再起動してください。

       

      セキュリティ・コンテキスト

      アクセス制御はセキュリティ・コンテキストというラベル付けされた情報をもとに行っています。
      ラベル付けされた情報はSELinuxユーザ: SELinuxユーザが認可されたロール:SELinuxがアクセスするタイプ:セキュリティレベルの4種類の要素で構成されています。

      202309_authorization_control_01

      例:root:staff_r :staff_t :s0-s0:c0.c1023

       

      SELinuxアクセス制御する機能

      SELinuxの機能がいくつかありますが、代表的な2つを紹介します。

      ・TE(Type Enforcement):プロセスがリソースにアクセスする権限を制御する機能

      TEではセキュリティポリシーを確認してリソースにアクセスします。
      例えば、httpd_tタイプはhttpd_sys_content_tのタイプに該当するリソースにアクセスを許可するというポリシーが含まれています。

      202309_authorization_control_02

      ・RBAC(Role Based Access Control):ロールと呼ばれる役割に応じたアクセス権をユーザに付与することでアクセス制御を行う機能

      その範囲内ならユーザがアクセスを制御することも可能であることからその点でDACとMACの中間的なモデルと言われることもあります。

      202309_authorization_control_03

      引用元:「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にアクセスさせたいファイル及びディレクトリのコンテキストを変更することで、ポリシー通りにアクセスできることが確認できました。

      まとめ

      今回は権限の制御で以下を説明しました。

      • ファイル属性のパーミッション
        • パーミッションとはファイルやディレクトリに設定されているアクセス権限のこと
        • 実行権限に関する特殊なパーミッションが3つある
      • ACL
        • 任意アクセス制御(DAC)モデル
        • パーミッションと比べ細やかにアクセス権限を設定可能
      • SELinux
        • 強制アクセス制御(MAC)モデル
        • セキュリティコンテキストというラベル情報を使って制御している

      次回の記事では暗号化について執筆予定です。ぜひそちらも御覧ください!

      【参考】

       LinuCイージス「Linux File-Permission」

      ファイルの ACL エントリ

      SELinux の機能概観

      SELinux の使用

      Webサーバーがサイトの構成ファイルを上書きできない問題に対応する(SELinuxが原因の場合)