File Permissions and ACLs

Linux ファイル権限と ACL - 包括的ガイド

目次

  1. はじめに
  2. 標準 Unix パーミッション
  3. 権限変更コマンド
  4. umask
  5. 特殊パーミッション
  6. ACL (Access Control Lists)
  7. SELinux コンテキストの基礎
  8. ファイル属性 (lsattr / chattr)
  9. パーミッション比較表
  10. 実践的セキュリティシナリオ
  11. トラブルシューティング
  12. ベストプラクティス
  13. 参考文献

1. はじめに

Linux のファイルパーミッションシステムは、DAC(任意アクセス制御)の中核をなす仕組みである。標準の Unix パーミッション、ACL、SELinux コンテキスト、そしてファイル属性を組み合わせることで、多層的なアクセス制御を実現できる。

本記事では、これらの仕組みを基礎から実践まで体系的に解説する。


2. 標準 Unix パーミッション

2.1 rwx の基本

Linux のすべてのファイルとディレクトリは、3つのエンティティに対してパーミッションが設定される。

-rwxr-xr-- 1 sysadmin developers 4096 Apr 10 12:00 script.sh
│├─┤├─┤├─┤
│ │   │  │
│ │   │  └── Others (その他)    : r-- (読み取りのみ)
│ │   └───── Group (グループ)   : r-x (読み取り+実行)
│ └───────── Owner (所有者)     : rwx (全権限)
└─────────── ファイルタイプ      : - (通常ファイル)

ファイルタイプ識別子:

文字種類
-通常ファイルテキスト、バイナリ等
dディレクトリフォルダ
lシンボリックリンクショートカット
cキャラクタデバイス/dev/tty
bブロックデバイス/dev/sda
p名前付きパイプ (FIFO)IPC 用
sソケット/var/run/*.sock

パーミッションの意味(ファイル vs ディレクトリ):

パーミッションファイルでの意味ディレクトリでの意味
r (read)ファイル内容の読み取りディレクトリ内の一覧表示
w (write)ファイル内容の変更ファイルの作成・削除・名前変更
x (execute)ファイルの実行ディレクトリへの移動(cd)

2.2 8進数表記

r = 4
w = 2
x = 1

組み合わせ表:

8進数記号意味
0---権限なし
1--x実行のみ
2-w-書き込みのみ
3-wx書き込み + 実行
4r--読み取りのみ
5r-x読み取り + 実行
6rw-読み取り + 書き込み
7rwx全権限

一般的な権限パターン:

8進数記号用途
755rwxr-xr-x実行ファイル、スクリプト
644rw-r--r--設定ファイル、HTMLファイル
600rw-------秘密鍵、パスワードファイル
700rwx------ホームディレクトリ、秘密ディレクトリ
750rwxr-x---グループ共有プログラム
775rwxrwxr-xグループ共有ディレクトリ
660rw-rw----グループ共有ファイル
440r--r-----/etc/sudoers
400r--------SSH 秘密鍵

2.3 ディレクトリに対するパーミッションの意味

# ディレクトリの各パーミッションの効果を検証
$ mkdir /tmp/test_perms && cd /tmp/test_perms

# r のみ(一覧は見えるが、cd やファイルアクセスは不可)
$ chmod 444 /tmp/test_perms
$ ls /tmp/test_perms
file1.txt  file2.txt
$ cat /tmp/test_perms/file1.txt
cat: /tmp/test_perms/file1.txt: Permission denied
$ cd /tmp/test_perms
bash: cd: /tmp/test_perms: Permission denied

# x のみ(cd は可能だが、一覧表示は不可。パスを知っていればアクセス可能)
$ chmod 111 /tmp/test_perms
$ cd /tmp/test_perms    # OK
$ ls /tmp/test_perms
ls: cannot open directory '/tmp/test_perms': Permission denied
$ cat /tmp/test_perms/file1.txt    # ファイル名を知っていればOK
Hello World

# r+x(通常の読み取り用ディレクトリ)
$ chmod 555 /tmp/test_perms
$ ls /tmp/test_perms    # OK
$ cat /tmp/test_perms/file1.txt    # OK
$ touch /tmp/test_perms/new.txt
touch: cannot touch '/tmp/test_perms/new.txt': Permission denied

3. 権限変更コマンド

3.1 chmod - パーミッション変更

シンボリックモード:

# 基本構文: chmod [who][operator][permission] file
# who:      u(user), g(group), o(others), a(all)
# operator: +(add), -(remove), =(set exactly)
# perm:     r, w, x, X, s, t

# 所有者に実行権限を追加
$ chmod u+x script.sh
$ ls -l script.sh
-rwxr--r-- 1 sysadmin developers 256 Apr 10 12:00 script.sh

# グループに書き込み権限を追加
$ chmod g+w config.yaml
$ ls -l config.yaml
-rw-rw-r-- 1 sysadmin developers 1024 Apr 10 12:00 config.yaml

# その他から全権限を削除
$ chmod o-rwx secret.key
$ ls -l secret.key
-rw-r----- 1 sysadmin developers 3243 Apr 10 12:00 secret.key

# 所有者に rwx、グループに rx、その他に権限なし(= で正確に設定)
$ chmod u=rwx,g=rx,o= deploy.sh
$ ls -l deploy.sh
-rwxr-x--- 1 sysadmin developers 512 Apr 10 12:00 deploy.sh

# 全員に実行権限を追加
$ chmod a+x public_script.sh

# 再帰的にディレクトリ配下を変更
$ chmod -R 750 /opt/myapp/

# X(大文字): ディレクトリにのみ実行権限を設定(ファイルは除外)
$ chmod -R u=rwX,g=rX,o= /var/www/html/
# → ディレクトリ: rwxr-x---
# → ファイル:     rw-r-----

8進数モード:

# 644: rw-r--r--
$ chmod 644 index.html

# 755: rwxr-xr-x
$ chmod 755 /usr/local/bin/myapp

# 600: rw-------
$ chmod 600 ~/.ssh/id_rsa

# 700: rwx------
$ chmod 700 ~/.ssh

# 再帰的に設定
$ find /var/www -type f -exec chmod 644 {} \;
$ find /var/www -type d -exec chmod 755 {} \;

# --reference: 別ファイルと同じパーミッションにする
$ chmod --reference=template.conf new.conf

3.2 chown - 所有者変更

# 所有者を変更
$ sudo chown webuser index.html
$ ls -l index.html
-rw-r--r-- 1 webuser developers 4096 Apr 10 12:00 index.html

# 所有者とグループを同時に変更
$ sudo chown webuser:www-data index.html
$ ls -l index.html
-rw-r--r-- 1 webuser www-data 4096 Apr 10 12:00 index.html

# グループのみ変更(:グループ名)
$ sudo chown :www-data index.html

# 再帰的に変更
$ sudo chown -R webuser:www-data /var/www/html/

# シンボリックリンク自体の所有者を変更(-h)
$ sudo chown -h webuser symlink_file

# --reference: 別ファイルと同じ所有者にする
$ sudo chown --reference=existing_file new_file

# 実行例
$ ls -la /var/www/html/
total 16
drwxr-xr-x 3 webuser www-data 4096 Apr 10 12:00 .
drwxr-xr-x 3 root    root     4096 Apr 10 12:00 ..
-rw-r--r-- 1 webuser www-data  612 Apr 10 12:00 index.html
drwxr-xr-x 2 webuser www-data 4096 Apr 10 12:00 css

3.3 chgrp - グループ変更

# グループを変更
$ sudo chgrp developers /opt/project/
$ ls -ld /opt/project/
drwxrwxr-x 5 root developers 4096 Apr 10 12:00 /opt/project/

# 再帰的に変更
$ sudo chgrp -R developers /opt/project/

# 実質的に chown :developers と同等
$ sudo chown :developers /opt/project/

4. umask

umask は、新規作成ファイル/ディレクトリのデフォルトパーミッションを制御する。

umask の計算方法:

ファイルのデフォルト:     666 (rw-rw-rw-)
ディレクトリのデフォルト: 777 (rwxrwxrwx)

実際の権限 = デフォルト - umask(ビット単位の補数演算)

umask 値とその効果:

umaskファイル権限ディレクトリ権限用途
022644 (rw-r--r--)755 (rwxr-xr-x)一般的(デフォルト)
077600 (rw-------)700 (rwx------)セキュア(プライベート)
027640 (rw-r-----)750 (rwxr-x---)グループ共有
002664 (rw-rw-r--)775 (rwxrwxr-x)グループ書き込み許可
007660 (rw-rw----)770 (rwxrwx---)グループ協業

実例:

# 現在の umask を確認
$ umask
0022

# シンボリック表示
$ umask -S
u=rwx,g=rx,o=rx

# umask が 022 の場合
$ touch testfile
$ mkdir testdir
$ ls -la
-rw-r--r-- 1 sysadmin sysadmin    0 Apr 10 12:00 testfile
drwxr-xr-x 2 sysadmin sysadmin 4096 Apr 10 12:00 testdir

# umask を変更(現在のシェルセッションのみ)
$ umask 077
$ touch securefile
$ mkdir securedir
$ ls -la
-rw------- 1 sysadmin sysadmin    0 Apr 10 12:01 securefile
drwx------ 2 sysadmin sysadmin 4096 Apr 10 12:01 securedir

# 永続的に umask を設定
# /etc/profile または ~/.bashrc に追加
$ echo "umask 027" >> ~/.bashrc

# PAM で umask を設定(全ユーザー適用)
# /etc/pam.d/common-session (Debian) or /etc/pam.d/system-auth (RHEL)
# session optional pam_umask.so umask=027

5. 特殊パーミッション

5.1 SUID (Set User ID)

ファイル実行時に、実行者ではなくファイル所有者の権限で実行される。

# SUID の表示(所有者の x が s になる)
$ ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 68208 Apr 10 12:00 /usr/bin/passwd

# SUID の設定
$ sudo chmod u+s /usr/local/bin/myapp
$ sudo chmod 4755 /usr/local/bin/myapp

# SUID ファイルの検索
$ find / -perm -4000 -type f 2>/dev/null
/usr/bin/passwd
/usr/bin/su
/usr/bin/sudo
/usr/bin/chage
/usr/bin/gpasswd
/usr/bin/newgrp
/usr/bin/mount
/usr/bin/umount
/usr/bin/pkexec
/usr/sbin/unix_chkpwd

# SUID の動作確認
# passwd は一般ユーザーが実行しても /etc/shadow(root所有)を更新できる
$ whoami
sysadmin
$ passwd    # /etc/shadow に書き込める(SUID により root 権限で実行)

SUID の注意点:

  • SUID はスクリプトファイルでは機能しない(セキュリティ上の理由)
  • SUID バイナリはセキュリティリスクの元になるため、定期的に監査する
  • 不要な SUID は削除する

5.2 SGID (Set Group ID)

ファイルに対する SGID: 実行時にファイルのグループ権限で実行される。

ディレクトリに対する SGID: ディレクトリ内で作成された新規ファイル/ディレクトリは、親ディレクトリのグループを継承する。

# SGID の表示(グループの x が s になる)
$ ls -ld /opt/shared/
drwxrwsr-x 2 root developers 4096 Apr 10 12:00 /opt/shared/

# SGID の設定
$ sudo chmod g+s /opt/shared/
$ sudo chmod 2775 /opt/shared/

# SGID ディレクトリの動作確認
$ sudo mkdir /opt/project
$ sudo chown root:developers /opt/project
$ sudo chmod 2775 /opt/project

# SGID なしの場合
$ mkdir /tmp/no_sgid
$ touch /tmp/no_sgid/test
$ ls -l /tmp/no_sgid/test
-rw-r--r-- 1 sysadmin sysadmin 0 Apr 10 12:00 test

# SGID ありの場合(グループが developers を継承)
$ touch /opt/project/newfile
$ ls -l /opt/project/newfile
-rw-rw-r-- 1 sysadmin developers 0 Apr 10 12:00 newfile

$ mkdir /opt/project/subdir
$ ls -ld /opt/project/subdir
drwxrwsr-x 2 sysadmin developers 4096 Apr 10 12:00 subdir
# → SGID も継承される

# SGID ファイルの検索
$ find / -perm -2000 -type f 2>/dev/null
/usr/bin/write
/usr/bin/wall
/usr/sbin/postdrop
/usr/sbin/postqueue

5.3 Sticky Bit

ディレクトリに設定すると、ファイルの削除/名前変更は所有者と root のみ可能になる。

# Sticky Bit の表示(その他の x が t になる)
$ ls -ld /tmp
drwxrwxrwt 18 root root 4096 Apr 10 12:00 /tmp

# Sticky Bit の設定
$ sudo chmod +t /opt/shared/
$ sudo chmod 1777 /opt/shared/

# Sticky Bit の動作確認
$ ls -ld /tmp
drwxrwxrwt 18 root root 4096 Apr 10 12:00 /tmp

# ユーザーAが作成したファイル
$ sudo -u usera touch /tmp/userA_file
$ ls -l /tmp/userA_file
-rw-r--r-- 1 usera usera 0 Apr 10 12:00 /tmp/userA_file

# ユーザーBは削除できない(Sticky Bit により保護)
$ sudo -u userb rm /tmp/userA_file
rm: cannot remove '/tmp/userA_file': Operation not permitted

# ファイル所有者は削除可能
$ sudo -u usera rm /tmp/userA_file    # OK

特殊パーミッション一覧:

名前8進数記号対象効果
SUID4000s (所有者x)ファイル所有者の権限で実行
SGID2000s (グループx)ファイルグループの権限で実行
SGID2000s (グループx)ディレクトリグループ継承
Sticky1000t (その他x)ディレクトリ削除保護

大文字 S/T の意味:

# 小文字 s/t: 基となる x パーミッションが有効
-rwsr-xr-x  # SUID + 実行権限あり

# 大文字 S/T: 基となる x パーミッションが無効(意味がない設定)
-rwSr-xr-x  # SUID はあるが実行権限がない → 実質無効
drwxrwxrwT  # Sticky Bit はあるがその他に x がない

6. ACL (Access Control Lists)

ACL は、標準の owner/group/others の枠を超えた細かなアクセス制御を提供する。

前提条件:

# ファイルシステムが ACL をサポートしているか確認
$ mount | grep "acl"
/dev/sda1 on / type ext4 (rw,relatime,acl)

# ACL パッケージのインストール(必要な場合)
$ sudo dnf install acl          # RHEL/CentOS
$ sudo apt install acl          # Debian/Ubuntu

6.1 getfacl - ACL の表示

# ACL の表示
$ getfacl /opt/project/report.txt
# file: opt/project/report.txt
# owner: sysadmin
# group: developers
user::rw-
user:auditor:r--
group::rw-
group:managers:r--
mask::rw-
other::---

# 複数ファイルの ACL を表示
$ getfacl -R /opt/project/

# ACL が設定されているファイルを確認
# ls -l で + マークが表示される
$ ls -l /opt/project/
-rw-rw----+ 1 sysadmin developers 4096 Apr 10 12:00 report.txt
-rw-rw-r--  1 sysadmin developers 2048 Apr 10 12:00 readme.txt
# ↑ "+" は ACL が設定されていることを示す

6.2 setfacl - ACL の設定

# 特定ユーザーに読み取り権限を付与
$ setfacl -m u:auditor:r /opt/project/report.txt

# 特定グループに読み書き権限を付与
$ setfacl -m g:managers:rw /opt/project/report.txt

# 複数の ACL エントリを同時に設定
$ setfacl -m u:auditor:r,g:managers:rw,g:contractors:r /opt/project/report.txt

# ACL の削除(特定エントリ)
$ setfacl -x u:auditor /opt/project/report.txt

# ACL の全削除
$ setfacl -b /opt/project/report.txt

# 再帰的に ACL を設定
$ setfacl -R -m g:developers:rwx /opt/project/

# 確認
$ getfacl /opt/project/report.txt
# file: opt/project/report.txt
# owner: sysadmin
# group: developers
user::rw-
user:auditor:r--
group::rw-
group:managers:rw-
group:contractors:r--
mask::rw-
other::---

mask の役割:

mask は ACL エントリの有効な最大権限を制限する。

# mask の設定
$ setfacl -m m::r /opt/project/report.txt

# 確認(effective 列が実際の有効な権限を表示)
$ getfacl /opt/project/report.txt
# file: opt/project/report.txt
# owner: sysadmin
# group: developers
user::rw-
user:auditor:r--
group::rw-                      #effective:r--
group:managers:rw-              #effective:r--
mask::r--
other::---
# → mask が r-- なので、group と ACL エントリは最大 r-- に制限される
# → owner と other は mask の影響を受けない

# chmod が mask に影響する
$ chmod 640 /opt/project/report.txt
# → グループの権限 (r--) が mask に反映される
$ getfacl /opt/project/report.txt
# ...
mask::r--

6.3 デフォルト ACL

デフォルト ACL は、ディレクトリ内で新規作成されるファイル/ディレクトリに自動適用される ACL。

# デフォルト ACL の設定
$ setfacl -d -m u::rwx /opt/project/
$ setfacl -d -m g::rwx /opt/project/
$ setfacl -d -m g:managers:rx /opt/project/
$ setfacl -d -m o::--- /opt/project/

# または一括で設定
$ setfacl -d -m u::rwx,g::rwx,g:managers:rx,o::--- /opt/project/

# デフォルト ACL の確認
$ getfacl /opt/project/
# file: opt/project
# owner: sysadmin
# group: developers
# flags: -s-
user::rwx
group::rwx
group:managers:r-x
other::---
default:user::rwx
default:group::rwx
default:group:managers:r-x
default:mask::rwx
default:other::---

# 動作確認: 新規ファイル作成
$ touch /opt/project/newfile.txt
$ getfacl /opt/project/newfile.txt
# file: opt/project/newfile.txt
# owner: sysadmin
# group: developers
user::rw-
group::rwx                      #effective:rw-
group:managers:r-x              #effective:r--
mask::rw-
other::---

# 動作確認: 新規ディレクトリ作成
$ mkdir /opt/project/subdir
$ getfacl /opt/project/subdir/
# file: opt/project/subdir
# owner: sysadmin
# group: developers
user::rwx
group::rwx
group:managers:r-x
mask::rwx
other::---
default:user::rwx
default:group::rwx
default:group:managers:r-x
default:mask::rwx
default:other::---
# → デフォルト ACL も継承される

# デフォルト ACL の削除
$ setfacl -k /opt/project/

6.4 ACL の継承

# 完全な共有ディレクトリ設定例
$ sudo mkdir -p /opt/teamproject
$ sudo chown root:developers /opt/teamproject
$ sudo chmod 2770 /opt/teamproject

# 基本的な ACL 設定
$ sudo setfacl -m g:developers:rwx /opt/teamproject
$ sudo setfacl -m g:managers:rx /opt/teamproject
$ sudo setfacl -m g:auditors:r /opt/teamproject

# デフォルト ACL 設定(新規作成物に継承される)
$ sudo setfacl -d -m g:developers:rwx /opt/teamproject
$ sudo setfacl -d -m g:managers:rx /opt/teamproject
$ sudo setfacl -d -m g:auditors:r /opt/teamproject
$ sudo setfacl -d -m o::--- /opt/teamproject

# ACL のバックアップと復元
$ getfacl -R /opt/teamproject > /tmp/teamproject_acl.bak
$ setfacl --restore=/tmp/teamproject_acl.bak

# ACL を別ディレクトリにコピー
$ getfacl /opt/teamproject | setfacl --set-file=- /opt/newproject

7. SELinux コンテキストの基礎

SELinux(Security-Enhanced Linux)は MAC(強制アクセス制御)を提供する。

SELinux コンテキストの表示

# ファイルの SELinux コンテキストを表示
$ ls -Z /var/www/html/index.html
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 /var/www/html/index.html
#                      ──────────── ──────── ──────────────────── ──
#                         user        role        type            level

# プロセスの SELinux コンテキスト
$ ps -eZ | grep httpd
system_u:system_r:httpd_t:s0  1234 ?  00:00:05 httpd

# 現在のユーザーの SELinux コンテキスト
$ id -Z
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

SELinux コンテキストの構造:

user:role:type:level
要素説明
userSELinux ユーザーsystem_u, unconfined_u
roleSELinux ロールobject_r, system_r
typeタイプ(最も重要)httpd_sys_content_t
levelMLS/MCS レベルs0

コンテキストの変更

# chcon - 一時的なコンテキスト変更(再ラベル付けで元に戻る)
$ sudo chcon -t httpd_sys_content_t /var/www/html/custom.html
$ ls -Z /var/www/html/custom.html
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 custom.html

# 再帰的に変更
$ sudo chcon -R -t httpd_sys_content_t /var/www/html/newsite/

# 別ファイルのコンテキストを参照して設定
$ sudo chcon --reference=/var/www/html/index.html /var/www/html/new_page.html

# restorecon - ポリシーに基づいてデフォルトに復元(推奨)
$ sudo restorecon -v /var/www/html/custom.html
Relabeled /var/www/html/custom.html from unconfined_u:object_r:default_t:s0
    to unconfined_u:object_r:httpd_sys_content_t:s0

# 再帰的に復元
$ sudo restorecon -Rv /var/www/html/

# semanage fcontext - 永続的なコンテキスト規則の追加
$ sudo semanage fcontext -a -t httpd_sys_content_t "/opt/mywebapp(/.*)?"
$ sudo restorecon -Rv /opt/mywebapp/

# 現在の SELinux モード確認
$ getenforce
Enforcing

# SELinux 関連のエラーを確認
$ sudo ausearch -m AVC -ts recent
$ sudo sealert -a /var/log/audit/audit.log

8. ファイル属性 (lsattr / chattr)

ファイル属性は、パーミッションとは別にファイルの動作を制御する仕組み。

lsattr - 属性の表示

$ lsattr /etc/resolv.conf
----i--------e----- /etc/resolv.conf
# i = immutable(変更不可)
# e = extent format(ext4のデフォルト)

$ lsattr -R /etc/ 2>/dev/null | grep -E "^-{4}i"
----i--------e----- /etc/resolv.conf

chattr - 属性の変更

# i (immutable): ファイルの変更・削除・名前変更・リンク作成を禁止
$ sudo chattr +i /etc/resolv.conf
$ echo "nameserver 8.8.8.8" >> /etc/resolv.conf
bash: /etc/resolv.conf: Operation not permitted
$ rm /etc/resolv.conf
rm: cannot remove '/etc/resolv.conf': Operation not permitted

# immutable を解除
$ sudo chattr -i /etc/resolv.conf

# a (append-only): 追記のみ可能(ログファイルに最適)
$ sudo chattr +a /var/log/secure_audit.log
$ echo "new entry" >> /var/log/secure_audit.log    # OK
$ echo "overwrite" > /var/log/secure_audit.log      # 失敗
bash: /var/log/secure_audit.log: Operation not permitted

# 追記属性を解除
$ sudo chattr -a /var/log/secure_audit.log

# A (no atime update): atime の更新を抑制(パフォーマンス向上)
$ sudo chattr +A /var/www/html/index.html

# s (secure delete): 削除時にブロックをゼロ埋め
$ sudo chattr +s /tmp/sensitive_data.txt

# S (synchronous): 書き込みを即座にディスクに反映
$ sudo chattr +S /var/lib/critical_db/data.mdb

主要な属性一覧:

属性文字説明
Immutablei一切の変更不可(root でも)
Append Onlya追記のみ可能
No AtimeAアクセス時刻を更新しない
Secure Deletes削除時にゼロ埋め
SynchronousS同期書き込み
No Dumpddump によるバックアップ対象外
Undeletableu削除しても復元可能(内容保持)
Compresscカーネルによる透過的圧縮
Extenteext4 のエクステント使用(自動設定)

9. パーミッション比較表

アクセス制御メカニズムの比較

機能標準パーミッションACLSELinuxファイル属性
制御の粒度owner/group/othersユーザー/グループ単位タイプベースファイル単位
設定コマンドchmod, chownsetfaclchcon, semanagechattr
確認コマンドls -lgetfaclls -Zlsattr
継承なしデフォルト ACLポリシールールなし
root による回避可能可能制限可能一部制限可能(immutable)
制御モデルDACDAC(拡張)MAC補助的
パフォーマンス影響最小最小
複雑さ

よく使うパーミッション設定の一覧

ファイル/ディレクトリ推奨権限所有者理由
/etc/shadow000 or 640root:shadowパスワードハッシュ保護
/etc/sudoers440root:rootsudo 設定保護
~/.ssh/700ユーザーSSH ディレクトリ
~/.ssh/id_rsa600ユーザーSSH 秘密鍵
~/.ssh/authorized_keys600ユーザーSSH 公開鍵リスト
/var/www/html/755root:rootWebコンテンツ
/var/www/html/*.html644root:root静的ファイル
/tmp1777root:root共有一時ディレクトリ
/var/log/755root:rootログディレクトリ
設定ファイル640root:group機密設定
cron ファイル600ユーザー個人 cron
SSL 証明書644root:root公開証明書
SSL 秘密鍵600root:root秘密鍵

10. 実践的セキュリティシナリオ

シナリオ 1: Web アプリケーションのデプロイディレクトリ

# 要件:
# - webadmin がコンテンツを管理
# - www-data (Apache/Nginx) が読み取り
# - その他はアクセス不可

$ sudo mkdir -p /var/www/myapp
$ sudo chown -R webadmin:www-data /var/www/myapp
$ sudo chmod 2750 /var/www/myapp    # SGID でグループ継承

# ディレクトリ配下の権限設定
$ sudo find /var/www/myapp -type d -exec chmod 2750 {} \;
$ sudo find /var/www/myapp -type f -exec chmod 640 {} \;

# CGI/スクリプトには実行権限
$ sudo chmod 750 /var/www/myapp/cgi-bin/*.cgi

# アップロードディレクトリ(Web サーバーが書き込み可能)
$ sudo mkdir /var/www/myapp/uploads
$ sudo chmod 2770 /var/www/myapp/uploads

# SELinux コンテキスト設定
$ sudo semanage fcontext -a -t httpd_sys_content_t "/var/www/myapp(/.*)?"
$ sudo semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/myapp/uploads(/.*)?"
$ sudo restorecon -Rv /var/www/myapp/

シナリオ 2: チーム共有プロジェクトディレクトリ

# 要件:
# - developers グループが完全アクセス
# - managers グループが読み取りアクセス
# - auditors が特定ファイルのみ読み取り
# - 他チームはアクセス不可

$ sudo mkdir -p /opt/project/alpha
$ sudo chown root:developers /opt/project/alpha
$ sudo chmod 2770 /opt/project/alpha

# ACL の設定
$ sudo setfacl -m g:managers:rx /opt/project/alpha
$ sudo setfacl -m g:auditors:r /opt/project/alpha

# デフォルト ACL(新規作成物に継承)
$ sudo setfacl -d -m u::rwx /opt/project/alpha
$ sudo setfacl -d -m g::rwx /opt/project/alpha
$ sudo setfacl -d -m g:managers:rx /opt/project/alpha
$ sudo setfacl -d -m g:auditors:r /opt/project/alpha
$ sudo setfacl -d -m o::--- /opt/project/alpha

# 設定確認
$ getfacl /opt/project/alpha
# file: opt/project/alpha
# owner: root
# group: developers
# flags: -s-
user::rwx
group::rwx
group:managers:r-x
group:auditors:r--
mask::rwx
other::---
default:user::rwx
default:group::rwx
default:group:managers:r-x
default:group:auditors:r--
default:mask::rwx
default:other::---

シナリオ 3: 重要設定ファイルの保護

# 重要な設定ファイルを immutable に設定
$ sudo chattr +i /etc/passwd
$ sudo chattr +i /etc/shadow
$ sudo chattr +i /etc/group
$ sudo chattr +i /etc/gshadow
$ sudo chattr +i /etc/sudoers

# ⚠️ 注意: ユーザー管理操作前に解除が必要
$ sudo chattr -i /etc/passwd /etc/shadow /etc/group /etc/gshadow

# 監査ログは append-only に設定
$ sudo chattr +a /var/log/auth.log
$ sudo chattr +a /var/log/secure

# 確認
$ lsattr /etc/passwd /etc/shadow /var/log/auth.log
----i--------e----- /etc/passwd
----i--------e----- /etc/shadow
-----a-------e----- /var/log/auth.log

シナリオ 4: 共有 /tmp の強化

# /tmp は別パーティションにマウント(推奨)
# /etc/fstab:
# tmpfs  /tmp  tmpfs  defaults,noexec,nosuid,nodev,size=2G  0  0

# Sticky Bit の確認
$ ls -ld /tmp
drwxrwxrwt 18 root root 4096 Apr 10 12:00 /tmp

# 古いファイルの定期削除
$ sudo systemd-tmpfiles --clean
# または
$ sudo find /tmp -type f -atime +7 -delete

11. トラブルシューティング

よくある問題と解決策

問題 1: Permission denied にもかかわらず権限があるように見える

# ACL の mask を確認
$ getfacl /opt/project/file.txt
# ...
group::rwx                      #effective:r--
mask::r--
# → mask が権限を制限している

# 解決: mask を修正
$ setfacl -m m::rwx /opt/project/file.txt

# SELinux が原因の場合
$ sudo ausearch -m AVC -ts recent | head -20
type=AVC msg=audit(...): avc:  denied  { read } for  pid=1234
    scontext=system_u:system_r:httpd_t:s0
    tcontext=unconfined_u:object_r:user_home_t:s0
# → httpd_t が user_home_t にアクセスできない

# 解決: 正しいコンテキストを設定
$ sudo restorecon -Rv /var/www/html/

問題 2: ファイルが削除できない

# immutable 属性を確認
$ lsattr problem_file
----i--------e----- problem_file

# 解決: immutable を解除
$ sudo chattr -i problem_file

# 親ディレクトリの権限を確認
$ ls -ld $(dirname problem_file)
# → 親ディレクトリに w+x が必要

問題 3: ACL が継承されない

# デフォルト ACL が設定されているか確認
$ getfacl /opt/project/ | grep default
# → 出力がなければデフォルト ACL が未設定

# 解決: デフォルト ACL を設定
$ setfacl -d -m g:developers:rwx /opt/project/

# ファイルシステムの ACL サポート確認
$ mount | grep "$(df /opt/project | tail -1 | awk '{print $1}')"
# → acl オプションが有効か確認

# fstab で有効化(必要な場合)
# /dev/sda1 /opt ext4 defaults,acl 0 2
$ sudo mount -o remount,acl /opt

問題 4: chmod が反映されない

# ファイルシステムのマウントオプション確認
$ mount | grep "/opt"
/dev/sda1 on /opt type ext4 (rw,nosuid,nodev)
# → nosuid がマウントされている場合、SUID/SGID は無効

# NFS の場合
$ mount | grep nfs
server:/export on /mnt/nfs type nfs4 (rw,nosuid,no_root_squash)
# → NFS の root_squash が影響する場合がある

パーミッション診断チェックリスト:

#!/bin/bash
# perm_check.sh <file_or_directory>
TARGET=$1

echo "=== ファイル情報 ==="
ls -la "$TARGET"
echo ""

echo "=== ACL ==="
getfacl "$TARGET" 2>/dev/null || echo "ACL 未対応"
echo ""

echo "=== ファイル属性 ==="
lsattr "$TARGET" 2>/dev/null || echo "属性取得不可"
echo ""

echo "=== SELinux コンテキスト ==="
ls -Z "$TARGET" 2>/dev/null || echo "SELinux 未対応"
echo ""

echo "=== マウントオプション ==="
df "$TARGET" | tail -1 | awk '{print $1}' | xargs -I{} mount | grep {}
echo ""

echo "=== 親ディレクトリ権限 ==="
ls -ld "$(dirname "$TARGET")"

12. ベストプラクティス

一般原則

  1. 最小権限の原則: 必要最小限の権限のみ付与する
  2. グループベースの管理: 個別ユーザーではなくグループで権限管理する
  3. SGID の活用: 共有ディレクトリには SGID を設定してグループ継承させる
  4. デフォルト ACL: 複雑な権限要件にはデフォルト ACL を使用する
  5. 定期的な監査: SUID/SGID ファイル、world-writable ファイルを定期チェック
  6. SELinux は Enforcing: 無効化せず、問題を正しく解決する
  7. immutable 属性: 重要な設定ファイルは chattr +i で保護する

セキュリティ監査スクリプト

#!/bin/bash
# security_audit.sh - ファイル権限の定期監査

echo "========================================="
echo " File Permission Security Audit"
echo " $(date)"
echo "========================================="

echo ""
echo "=== 1. SUID ファイル一覧 ==="
find / -perm -4000 -type f 2>/dev/null | sort

echo ""
echo "=== 2. SGID ファイル一覧 ==="
find / -perm -2000 -type f 2>/dev/null | sort

echo ""
echo "=== 3. World-writable ファイル(/tmp, /var/tmp 除外)==="
find / -perm -002 -type f ! -path "/tmp/*" ! -path "/var/tmp/*" \
    ! -path "/proc/*" ! -path "/sys/*" 2>/dev/null | sort

echo ""
echo "=== 4. World-writable ディレクトリ(Sticky Bit なし)==="
find / -perm -002 -type d ! -perm -1000 \
    ! -path "/proc/*" ! -path "/sys/*" 2>/dev/null | sort

echo ""
echo "=== 5. 所有者のないファイル ==="
find / -nouser -o -nogroup 2>/dev/null | head -20

echo ""
echo "=== 6. パスワード未設定アカウント ==="
sudo awk -F: '$2 == "" {print $1}' /etc/shadow

echo ""
echo "=== 7. 重要ファイルの権限チェック ==="
for f in /etc/passwd /etc/shadow /etc/group /etc/gshadow /etc/sudoers; do
    perms=$(stat -c "%a %U:%G" "$f" 2>/dev/null)
    echo "  $f : $perms"
done

echo ""
echo "=== 8. SSH 設定の権限チェック ==="
for home in /home/*; do
    user=$(basename "$home")
    if [ -d "$home/.ssh" ]; then
        echo "  $user:"
        stat -c "    %n : %a" "$home/.ssh" "$home/.ssh/"* 2>/dev/null
    fi
done

権限設定テンプレート(Ansible Playbook 例)

# file_permissions.yml
---
- name: Enforce file permissions
  hosts: all
  become: yes
  tasks:
    - name: Set critical file permissions
      file:
        path: "{{ item.path }}"
        mode: "{{ item.mode }}"
        owner: "{{ item.owner }}"
        group: "{{ item.group }}"
      loop:
        - { path: '/etc/passwd',  mode: '0644', owner: 'root', group: 'root' }
        - { path: '/etc/shadow',  mode: '0000', owner: 'root', group: 'root' }
        - { path: '/etc/group',   mode: '0644', owner: 'root', group: 'root' }
        - { path: '/etc/gshadow', mode: '0000', owner: 'root', group: 'root' }
        - { path: '/etc/sudoers', mode: '0440', owner: 'root', group: 'root' }

    - name: Configure shared project directory
      file:
        path: /opt/project
        state: directory
        mode: '2770'
        owner: root
        group: developers

    - name: Set ACL on shared project directory
      acl:
        path: /opt/project
        entity: managers
        etype: group
        permissions: rx
        state: present

    - name: Set default ACL for inheritance
      acl:
        path: /opt/project
        entity: developers
        etype: group
        permissions: rwx
        default: yes
        state: present

    - name: Protect critical config files with immutable flag
      command: "chattr +i {{ item }}"
      loop:
        - /etc/resolv.conf
        - /etc/hosts
      changed_when: false

13. 参考文献


文書情報

  • 作成日: 2026-04-10
  • 対象OS: RHEL 8/9, CentOS Stream 8/9, Ubuntu 22.04/24.04, Debian 12
  • 生成: AI Generated Technical Article