chgrp -R nobody /whatever
を実装したい場合 setuid ビットを保持しながら、これら 2 つの find
を使用できます コマンド
find /whatever ! -type l -perm -04000 -exec chgrp nobody {} + \
-exec chmod u+s {} +
find /whatever ! -type l ! -perm -04000 -exec chgrp nobody {} +
find ... -perm 04000
オプションは、setuid ビットが設定されたファイルを取得します。最初のコマンドは chgrp
を適用します そして chmod
ノックオフされた setuid ビットを元に戻します。 2 つ目は chgrp
を適用します setuid ビットを持たないすべてのファイルに。
いずれにせよ、chgrp
を呼び出したくありません。 または chmod
代わりにターゲットに影響を与えるため、シンボリックリンクで、 ! -type l
.
chgrp
で SUID および SGID ビットをクリアする (または chown
) は完全に合理的です。セキュリティ上の問題を防ぐための安全対策です。 SGID の場合 (実行可能ファイルでは、おそらく) は、グループ所有者の有効なグループでこのプログラムを実行することを意味します .
グループ所有者を変更すると、セキュリティとアクセス制御の観点から、これはまったく別のものになります。つまり、有効なグループ uvw
で実行する代わりに プログラムは有効なグループ xyz
で実行されるようになりました .
したがって、所有権の変更時に SUID または SGID ビットを明示的に復元する必要があります。
補遺:chgrp (または chown) は SGID (または SUID) のみをクリアする必要があるという主張について
chown
で ing または chgrp
実行可能ファイルのセキュリティ設定を変更すると、権限昇格属性をクリアする十分な理由になります。 Unix の力は概念の単純さから生まれますが、Unix のセキュリティはすでに非常に複雑です。この目的を達成するために、所有権の変更時に SUID と SGID を削除することは、単なるセーフティ ネットです。結局のところ、Unix/Linux の歴史の中で、SUID または SGID の設定の誤りによるかなりの脆弱性がありました。
したがって、Unix がこのように動作する理由はこれ以上ありません。これは保守的な設計上の決定にすぎません。
setuid
のクリア 、 setgid
ディレクトリ以外でのビット (少なくとも Linux では) は、chown()
時にカーネルによって行われます。 chgrp
によって実行されたシステム コール 、 chgrp
ではありません 自体。したがって、唯一の方法は後で復元することです。
セキュリティ機能もクリアします。
したがって、GNU Linux では:
chown_preserve_sec() (
newowner=${1?}; shift
for file do
perms=$(stat -Lc %a -- "$file") || continue
cap=$(getfattr -m '^security\.capability$' --dump -- "$file") || continue
chown -- "$newowner" "$file" || continue
[ -z "$cap" ] || printf '%s\n' "$cap" | setfattr --restore=-
chmod -- "$perms" "$file"
done
)
実行します (root
として) ):
chown_preseve_sec :newgroup file1 file2...
権限を維持しながらグループを変更します。
再帰的に、次のことができます:
# save permissions (and ACLs). Remove the "# owner" and "# group" lines
# to prevent them being restored!
perms=$(getfacl -RPn . | grep -vE '^# (owner|group): ')
# save capabilities
cap=$(getfattr -Rhm '^security\.capability$' --dump .)
chgrp -RP nobody .
# restore permissions, ACLs and capabilities
printf '%s\n' "$perms" | setfacl --restore=-
[ -z "$cap" ] || printf '%s\n' "$cap" | setfattr -h --restore=-
(それ以外の方法で同時にファイルを台無しにするものはないと仮定しています)。