シェルスクリプト実行権限を安全に管理する|setuidを使わない配布設計

運営:リナックスマスター.JP(代表 宮崎智広)
HOME > Linux技術 リナックスマスター.JP(Linuxマスター.JP) > シェルスクリプト > シェルスクリプト実行権限を安全に管理する|setuidを使わない配布設計
「スクリプトに実行権限を付けたのに動かない」「setuidを立てても特権で動かない」——シェルスクリプトを配布・配置する場面でつまずくポイントは意外に多いです。

この記事では、RHEL 9系/Rocky Linux 9を想定環境として、シェルスクリプトの実行権限を正しく設計・配布する方法と、setuidが使えないLinuxの制約に対する安全な代替手段を解説します。

この記事のポイント

・Linuxカーネルはインタープリタ系スクリプトのsetuidビットを意図的に無視する
・chmod +x と所有者設計の組み合わせがスクリプト配布の基本
・特権操作にはsudoers設定またはCラッパーによる代替設計が安全
・「Permission denied」は実行ビット・ディレクトリ権限・SELinuxの順に確認する


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

なぜシェルスクリプトにsetuidが効かないのか

setuidビット(chmod u+s)は本来、ファイルをオーナーの権限で実行させる仕組みです。ところがLinuxでは、シェルスクリプトを含むインタープリタ型ファイルのsetuidを意図的に無視します。

理由はセキュリティ上の制約です。シェルスクリプトの実行は「まず/bin/bash(インタープリタ)が起動し、スクリプトを引数として読み込む」という二段階になります。このとき、/bin/bashに渡す前の一瞬にシンボリックリンク差し替え攻撃(TOCTOU: Time-Of-Check to Time-Of-Use)が成立してしまうため、Linuxカーネルは設計上setuidを無効にしています。

結果として、setuidビットを設定しても無害に無視されるだけです。

# setuidビットを立ててもlsで確認するとsビットは見えるが実行時は無視される $ chmod u+s /usr/local/bin/backup.sh $ ls -la /usr/local/bin/backup.sh -rwsr-xr-x 1 root root 512 Oct 28 10:00 backup.sh # 一般ユーザーで実行しても root 権限にはならない(wohoami の出力は alice のまま) $ /usr/local/bin/backup.sh

出力例(環境により異なります)

「setuidを立てれば特権でスクリプトを動かせる」という思い込みが配布設計の誤りの根本です。

chmod +x と実行権限の基本設計

setuidは使えないとわかったうえで、スクリプトを安全に配布するための基本設計を押さえましょう。

1. シェバン行と実行ビットの両方を整える

スクリプトを直接実行(./script.sh)するには2つの条件が揃う必要があります。シェバン行(1行目の #!/bin/bash)と、実行ビット(chmod +x)の両方です。どちらが欠けても「Permission denied」または「bad interpreter」エラーになります。

# 実行ビットを付与する(配布先での基本手順) chmod 755 /usr/local/bin/backup.sh # 全ユーザーが実行可能 chmod 750 /usr/local/bin/backup.sh # オーナーとグループのみ実行可能 chmod 700 /usr/local/bin/backup.sh # オーナーのみ実行可能

現場では 755 を選ぶ場面が多いですが、内部処理(バックアップ先・認証情報を参照するスクリプトなど)は 750 以下にするのが原則です。

2. 所有者とグループの設計

スクリプトの実行可否は「誰が所有者か・どのグループに属するか」で決まります。

運用スクリプトを複数のオペレーターに使わせたい場合は、専用グループ(例: ops)を作成し、そのグループに実行権限を付ける設計が安全です。

# スクリプトを root 所有・ops グループで管理する例 chown root:ops /usr/local/bin/backup.sh chmod 750 /usr/local/bin/backup.sh # → root と ops グループメンバーのみ実行可能(その他のユーザーはアクセス不可) # ユーザーを ops グループに追加する usermod -aG ops alice

3. 配置先ディレクトリのパーミッション

スクリプト自身の権限が正しくても、配置先ディレクトリに実行権限(x)がなければ「Permission denied」になります。

# ディレクトリの実行権限を確認する ls -la /usr/local/ # drwxr-xr-x 12 root root 4096 Oct 28 10:00 /usr/local/ ← r-x があれば OK # 問題例: ディレクトリが 700 だと他のユーザーはスクリプトに到達できない ls -la /opt/myapp/ # drwx------ 2 root root 4096 Oct 28 09:00 /opt/myapp/ ← alice はアクセス不可

出力例(環境により異なります)

ディレクトリにxビットがなければ、中のファイルのパーミッションに関係なくアクセス自体が遮断されます。配布時は配置先ディレクトリの権限も必ず確認してください。

setuidを使わない特権操作の3つの代替手段

特定の処理にどうしても昇格権限が必要な場合は、以下の代替手段を検討します。setuidに頼らず、より安全に同じ目的を達成できます。

シェルスクリプトの権限設計・配布設計についてさらに深く学びたい方は、シェルスクリプト実践入門(LinuxMaster.JP)をあわせてご覧ください。

1. sudoersで特定スクリプトだけに許可を絞る

最もよく使われる方法です。visudoコマンドで /etc/sudoers に1行追加するだけで、特定の一般ユーザーが特定のスクリプトのみをパスワードなしでroot権限で実行できるようになります。

# /etc/sudoers に追加(必ず visudo コマンドで編集する) alice ALL=(root) NOPASSWD: /usr/local/bin/backup.sh # alice がパスワードなしで実行できる sudo /usr/local/bin/backup.sh

ポイントは「スクリプトの絶対パスを必ず指定する」ことです。スクリプト自身に書き込み権限を与えない(chmod 755 以下・オーナーを root にする)ことで、内容を差し替えられるリスクを防ぎます。

・許可ユーザー:特定ユーザー・グループ単位で絞り込める
・パスワード要否:NOPASSWDで省略可能(自動化cron向け)
・引数制限:スクリプトパスの後に引数パターンを書くと引数レベルでも制限できる

2. Cラッパーバイナリでsetuidを安全に使う

どうしてもsetuidで動かしたい処理がある場合は、シェルスクリプトではなくCで書いたラッパーバイナリを間に挟みます。バイナリはTOCTOU攻撃の影響を受けないため、setuidが安全に機能します。

/* wrapper.c — シェルスクリプトをroot権限で呼び出すCラッパーの例 */ #include <unistd.h> int main() { setuid(0); execl("/bin/bash", "bash", "/usr/local/bin/backup.sh", (char *)0); return 1; }

# コンパイルしてsetuidを設定する gcc -o /usr/local/bin/backup-wrapper wrapper.c chown root:root /usr/local/bin/backup-wrapper chmod 4755 /usr/local/bin/backup-wrapper # 4=setuidビット有効

この方法はスクリプトを変更するたびにラッパーの再コンパイルは不要ですが、実装の複雑さが増します。シンプルな運用が求められる場面では sudoers 方式を優先してください。

3. Linux capabilitiesで最小権限を付与する

「root全権は要らないが、特定のシステムコールだけ昇格させたい」という場合はLinux capabilitiesが有効です。ただし、シェルスクリプト自体にはcapabilitiesを付与できないため、専用バイナリを経由する必要があります。

# 例: バイナリに net_admin capability のみを付与 setcap cap_net_admin+ep /usr/local/bin/net-tool # 付与した capabilities を確認 getcap /usr/local/bin/net-tool # /usr/local/bin/net-tool = cap_net_admin+ep # 削除する場合 setcap -r /usr/local/bin/net-tool

capabilitiesを付与するのは権限を最小化できる反面、対象のバイナリがインタープリタ(Pythonなど)の場合は影響範囲が広がるため注意が必要です。実務では専用の小さなバイナリに絞って付与するのが安全な設計です。

配布設計のチェックリスト

スクリプトを新しいサーバーに配布・配置するときに確認する手順をまとめます。

・シェバン行:1行目に #!/bin/bash(または /bin/sh)が記載されているか
・実行ビット:chmod で x ビットが付いているか(ls -la で確認)
・所有者:セキュリティ要件に合った chown 設定になっているか
・グループ:実行させたいユーザーがグループメンバーになっているか(id で確認)
・配置先ディレクトリ:x ビットがあり実行ユーザーがアクセスできるか
・setuid:スクリプトに setuid を設定しない(設定しても無視される・混乱の元)
・書き込み権限:他者がスクリプトに書き込めないか(777 は厳禁。sudoers 対象スクリプトは 755 以下・root 所有)
・改行コード:WindowsのCR+LFが混入していないか(file script.sh で確認)

「Permission denied」が出た時の対処法

スクリプトの実行権限まわりで「Permission denied」が出たときの調査手順を整理します。

# ステップ1: スクリプト自身の権限と所有者を確認する ls -la /path/to/script.sh # ステップ2: 配置先ディレクトリのパーミッションを確認する ls -la /path/to/ # ステップ3: 実行ユーザーのグループ所属を確認する id alice # ステップ4: SELinuxが遮断していないか確認する(RHEL・Rocky Linux系) ls -Z /path/to/script.sh ausearch -m AVC -ts recent | grep script.sh

出力例(環境により異なります)

「bad interpreter: No such file or directory」はシェバン行のパスが間違っているか、Windows改行コード(CR+LF)が混入しているケースです。

# Windows改行コードの混入チェックと除去 file script.sh # script.sh: Bash script, ASCII text executable, with CRLF line terminators # sed で CR を除去する sed -i 's/ //' script.sh

SELinuxが有効な環境では、パーミッションが正しくてもSELinuxのポリシーで実行が遮断される場合があります。ausearchでAVCデナイアルを確認してから対処してください。

本記事のまとめ

シェルスクリプトの実行権限設計と配布のポイントをまとめます。

やりたいこと 正しい手段
スクリプトを実行可能にする chmod 755 script.sh
特定グループだけに実行許可 chown root:ops script.sh && chmod 750 script.sh
一般ユーザーに特権スクリプト実行を許可する visudo で NOPASSWD 設定
setuid で特権実行(スクリプトには不可) C ラッパーバイナリに setuid を適用
最小権限の付与 setcap で capability を限定付与
「Permission denied」の調査 ls -la + id + ausearch(SELinux)の順に確認

setuidはシェルスクリプトに立てても無視されます。特権操作が必要な場面では sudoers による絞り込みか、Cラッパーを使った設計に切り替えることで、セキュリティを保ちながら要件を満たせます。配布時は「実行ビット・所有者・配置先ディレクトリ」の3点を必ず確認するようにしてください。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、シェルスクリプトの権限設計・配布設計を含む実践的なLinux運用スキルを2日間で習得できるセミナーを開催しています。

>> シェルスクリプト実践入門|LinuxMaster.JP

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録

運営

リナックスマスター.JP(代表 宮崎智広)

株式会社イーネットマーキュリーが運営するLinux教育サイトです。代表の宮崎智広は現役のLinuxサーバー管理者として20年以上の実務経験を持ち、累計3,100名以上のエンジニアを指導してきました。実践型のLinuxセミナーや無料マニュアルの配布を通じてLinux人材の育成に取り組んでいます。