chgrp が「setuid ビット」をクリアするのを防ぐにはどうすればよいでしょうか?

chgrp が「setuid ビット」をクリアするのを防ぐにはどうすればよいでしょうか?

当社には RH ベースの Linux イメージがあり、これを当社製品の最新の開発バージョンにアップグレードするには、何らかの「特別なアーカイブ」を「適用」する必要があります。

アーカイブを作成した人は、ベースイメージ内の一部の権限が間違っていることに気づいたので、

sudo chgrp -R nobody /whatever

私たちはそれを実行しましたが、その後、アプリケーションの実行中に、不明な問題が発生しました。

後で見つけたのは、chgrp意思クリア/whatever 内のバイナリの setuid ビット情報。

そして実際の問題は、私たちのバイナリの一部がしなければならない正常に機能するには、setuid ビットを設定する必要があります。

簡単に言うと、「chgrp」コマンドを実行する方法はありますか?それなし私のsetuidビットを殺すのですか?

ローカルの Ubuntu で以下を実行したところ、同じ結果になりました。

mkdir sticky
cd sticky/
touch blub
chmod 4755 blub 
ls -al blub 

--> ファイル名が赤い背景で表示されます --> つまり、setuid です

chgrp -R myuser .
ls -al blub 

--> 赤い背景なしでファイル名が表示されます --> setuid は消えています

答え1

chgrp -R nobody /whateversetuidビットを保持したまま実装したい場合は、次の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 番目のコマンドは、chgrpsetuid ビットを持たないすべてのファイルに適用されます。

いずれにしても、シンボリック リンクでchgrpまたはを呼び出すchmodと、代わりにそのターゲットに影響するため、 が必要になります! -type l

答え2

chgrp(または)のSUIDとSGIDビットをクリアすることchownは完全に合理的です。これはセキュリティ上の問題を防ぐための安全策です。SGID(実行可能ファイルの場合、おそらく)の場合、このプログラムをグループ所有者の有効なグループで実行する

グループの所有者を変更すると、セキュリティとアクセス制御の観点ではまったく異なるものになります。つまり、uvwプログラムは有効なグループで実行されるのではなく、有効なグループで実行されるようになりますxyz

したがって、所有権の変更時には SUID または SGID ビットを明示的に復元する必要があります。

補遺: chgrp (または chown) はそれぞれ SGID (または SUID) のみをクリアする必要があるという主張について

chownまたは を実行するとchgrp、実行可能ファイルのセキュリティ設定が変更されます。これは、権限を昇格する属性をすべてクリアする十分な理由になります。Unix のパワーは概念の単純さから生まれ、Unix のセキュリティはすでに非常に複雑です。このため、所有権の変更時に SUID と SGID を削除することは、単に安全策です。結局のところ、Unix/Linux の歴史では、誤った SUID または SGID 設定による脆弱性がかなりありました。

したがって、Unix がこのように動作する理由は特になく、単に保守的な設計上の決定です。

答え3

setuidディレクトリ以外の,ビットのクリアはsetgid(少なくとも Linux では)、 によるchown()システム コール時にカーネルによって行われchgrpchgrp自体によって行われるわけではありません。したがって、唯一の方法は、後でそれを復元することです。

セキュリティ機能もクリアします。

つまり、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=-

(これはすべて、同時にファイルに何か他の問題が起きていないことを前提としています)。

答え4

管理においてはいつものことながら、やり方はいろいろあります。

私が実施した解決策は次のようになります。

cd /home/me
getfacl -R /whatever > whatever-permissions.org 2> /dev/null

# A) change lines starting with      # group: root
# to                                 # group: whatineed
sed 's/^# group: root/# group: whatineed/g' whatever-permissions.org > whatever-permissions.new

# B) change lines with               group::x.y
# to                                 group::xwy
# (where x, y mean: whatever was there before)
sed 's/^group::\(.\).\(.\)/group::\1w\2/g' whatever-permissions.new > whatever-permissions.new

cd /
setfacl --restore /home/me/whatever-permissions.new

関連情報