sudo/suの使い分け - 権限昇格の安全な方法
この記事でできるようになること
- sudo と su を目的に応じて使い分けられる
- sudo が推奨される理由をセキュリティ観点で説明できる
- visudo で sudoers を安全に編集できる
前提知識(先に読むと理解しやすい記事)
この記事で身につくこと
sudoとsuを、目的に応じて使い分けられるようになります。- なぜ
suよりsudoが推奨されるのかを、セキュリティ観点で説明できるようになります。 sudoersの基本設定を、自分で安全に書けるようになります。- よくある事故パターンとその回避策が分かるようになります。
想定読者:Ubuntu でサーバを触りはじめ、sudo を「おまじない」として打っている人。
先に用語を整理する
初めて出てくる言葉を、ここで一度だけ定義します。
- 権限昇格とは、今のユーザーでは許されていない操作を、より強い権限で実行することです。「特権昇格」「privilege escalation」とも呼びます。
- root(ルート)とは、システム上で何でもできる管理者ユーザーの名前です。「スーパーユーザー」とも呼びます。
- ログインシェルとは、ログイン時に読み込まれる設定(
.profileや.bashrc)を反映した状態のシェルです。同じユーザーでも、ログインシェルかどうかでPATHなどの環境変数が変わります。 - 環境変数とは、シェルが持っている設定値です。
PATH(コマンドを探す場所の一覧)やHOME(ホームディレクトリ)が代表例です。 - sudoers とは、誰にどのコマンドを許可するかを書いた設定ファイル
/etc/sudoersのことです。 - visudo とは、
sudoersを構文チェック付きで編集する専用コマンドです。 - NOPASSWD とは、sudoers に書ける指定で、パスワード入力を省略して実行を許可する設定です。
結論(実務の型)
- 1コマンドだけ root 権限が必要 →
sudo command - root として複数操作する(やむを得ない場合のみ) →
sudo -i - 別ユーザーとして1コマンド実行 →
sudo -u username command su -は root パスワードが必要。Ubuntu のデフォルトでは root パスワードが無効なため使えない
前提(対象環境)
- OS:Ubuntu(または Debian 系)
- 作業ユーザーが
sudoグループに追加済み
1. sudo と su の違いは何か?
sudo(substitute user do)と su(switch user)は、どちらも権限昇格のためのコマンドだが、仕組みが根本的に異なる。
| 項目 | sudo | su |
|---|---|---|
| 認証 | 自分のパスワード | 切り替え先のパスワード |
| root パスワード | 不要 | 必要(su - の場合) |
| 操作ログ | /var/log/auth.log に記録 |
記録が弱い |
| 権限範囲 | /etc/sudoers で細かく制御 |
root に全権限を渡す |
| Ubuntu デフォルト | 使用可能 | root パスワード無効で使えない |
sudo はユーザーごとに許可コマンドを限定できる点がセキュリティ上の強みだ。root パスワードをチームで共有する必要もない。
2. sudo の使い方
2-1. 基本形:1コマンドだけ実行
$ sudo command
例:
$ sudo apt update $ sudo systemctl restart nginx
2-2. root のログインシェルを起動する
$ sudo -i
sudo -i は root の環境変数と .profile を読み込んだ状態でシェルを起動する。長時間の root 作業が必要な場合に使う。
root シェルを起動したままにしないこと。作業が終わったら exit で抜ける。
2-3. 別ユーザーとして実行する
$ sudo -u username command
例:www-data ユーザーとしてコマンドを実行:
$ sudo -u www-data php /var/www/html/artisan cache:clear
2-4. 権限昇格の持続時間
sudo は初回認証後、デフォルト 15 分間はパスワードなしで再実行できる。タイムアウトを即座にリセットする場合:
$ sudo -k
現在の自分の sudo 権限を確認する:
$ sudo -l
User alice may run the following commands on hostname:
(ALL : ALL) ALL
(ALL : ALL) ALL は「どのユーザーとしても、どのコマンドでも実行できる」という意味。特定コマンドだけ許可されている場合は、そのコマンドのパスが列挙される。
3. su の使い方
3-1. su - でログインシェルを起動
$ su - [username]
- オプション(-l / --login と同義)は、切り替え先ユーザーのログイン環境(ホームディレクトリ・環境変数・PATH)を再現する。
$ su - deploy # deploy ユーザーのログインシェルを起動
3-2. su と su - の違い
$ su username # NG:現在の環境変数をそのまま引き継ぐ $ su - username # OK:ログイン時と同じ環境を再現
su username(- なし)は現在の環境変数を引き継ぐため、切り替え先のユーザー環境が正しく再現されない。特に PATH が混在して command not found になる事故が多い。
3-3. Ubuntu で su が使えない理由
Ubuntu のデフォルトでは root アカウントのパスワードが無効化されている。su - で root に切り替えようとすると認証に失敗する。
$ su - Password: su: Authentication failure # root パスワードが無効
Ubuntu で root シェルが必要な場合は sudo -i を使う。
4. なぜ sudo が推奨されるのか?
sudo が推奨される理由はセキュリティモデルの違いにある。
操作ログが残る: sudo を実行するたびに /var/log/auth.log に「誰が・何時・何のコマンドを実行したか」が記録される。
# rsyslog がある環境(Ubuntu 22.04 など) $ sudo grep sudo /var/log/auth.log | tail -3 # journald のみの環境(Ubuntu 24.04 の既定インストールなど) $ sudo journalctl -t sudo -n 3
May 31 10:30:01 hostname sudo: alice : TTY=pts/0 ; PWD=/home/alice ; USER=root ; COMMAND=/usr/bin/apt update
Ubuntu 24.04 は既定インストールで rsyslog を含まないため、/var/log/auth.log が存在しない構成がある。その場合はログが journald に集約されているため journalctl 側を使う。
「誰が」「どのディレクトリで」「どのコマンドを」実行したかが 1 行に残る。障害時に操作を追跡できるのは、この記録があるからだ。
最小権限の原則: sudoers でコマンドを個別に許可できるため、特定ユーザーに必要最低限の権限だけを付与できる。
root パスワード不要: チームメンバーに root パスワードを教える必要がない。個人の資格情報で認証が完結する。
5. sudoers の設定(visudo)
5-1. visudo で安全に編集する
/etc/sudoers は必ず visudo コマンドで編集する。visudo はファイルを保存する前に構文チェックを行い、設定ミスでシステムにアクセスできなくなる事故を防ぐ。
$ sudo visudo
/etc/sudoers の直接編集は禁止
/etc/sudoers を vi や nano で直接編集しないこと。失敗するとどうなるかは次のとおり。
- 構文を 1 文字ミスすると
sudo自体が動作不能になる。 - Ubuntu は root パスワードが無効なため、
su -での復旧もできない。物理コンソールからリカバリモードで起動する必要が生じる。 - SSH 越しの作業でこれが起きた場合、そのサーバに管理者として入れなくなる。
安全に試す方法は次の 3 つ。
- 編集は必ず
sudo visudoで行う。保存時に構文チェックが走り、エラーがあれば書き込みを拒否してくれる。 - 練習は本番サーバではなく、手元の仮想マシンやコンテナで行う。
- 作業前に別のターミナルで
sudo -vが通る状態のセッションを開いたままにしておく。万一 sudoers を壊しても、そのセッションから修正できる。
5-2. 基本的な書式
# ユーザー ホスト=(実行ユーザー) コマンド alice ALL=(ALL) ALL # NOPASSWD:パスワードなしで特定コマンドを許可 deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx
5-3. グループに対して許可する
# %グループ名 で指定 %admin ALL=(ALL) ALL %deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl
5-4. drop-in ファイルで管理する(推奨)
大規模環境では sudoers 本体を直接編集せず、/etc/sudoers.d/ 配下にファイルを置く方法が推奨される。
$ sudo visudo -f /etc/sudoers.d/deploy
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx
6. よくある事故パターン
NOPASSWD を全コマンドに設定する
# 危険:何でもパスワードなしで実行できる alice ALL=(ALL) NOPASSWD: ALL
開発環境の「楽さ」のために設定したまま本番に持ち込むと深刻なリスクになる。このユーザーのセッションを奪われた時点で、攻撃者はパスワードを知らずに root 相当の操作ができる。許可は特定コマンドのみに限定すること。
visudo を使わずに sudoers を編集する
直接 vi /etc/sudoers で編集して構文ミスを起こすと、sudo が動作不能になる。visudo は保存時に構文チェックを行うため、必ず使うこと。
su username で環境変数が混在する
# NG:PATH が現在のシェルの設定を引き継ぐ $ su deploy # OK:deploy のログイン環境を再現 $ su - deploy
トラブルシューティング
症状: alice is not in the sudoers file. This incident will be reported.
原因: そのユーザーが sudo グループ(RHEL 系では wheel)に所属していない。
確認:
id -nG
alice
sudo が含まれていなければ権限がない。
対処: 別の管理者権限を持つユーザーから追加してもらう。
sudo usermod -aG sudo alice # 管理者側で実行
追加後は、対象ユーザーがログアウトして再ログインするまで反映されない。管理者が誰もいない場合は、物理コンソールからリカバリモードで起動して修正する。
症状: sudo: unable to resolve host <hostname>
原因: /etc/hostname の名前が /etc/hosts に登録されていない。sudo 自体は動くが、毎回この警告が出る。
確認:
hostname grep "$(hostname)" /etc/hosts
対処: /etc/hosts の 127.0.0.1 の行に現在のホスト名を追記する。編集前にコピーを取っておくと戻せる。
sudo cp /etc/hosts /etc/hosts.bak sudo nano /etc/hosts
127.0.0.1 localhost myhost
症状: sudo: no tty present and no askpass program specified
原因: cron やスクリプトなど端末のない環境で、パスワード入力を求める sudo を実行した。
確認: 実行元が cron / systemd / CI などの非対話環境かどうかを確認する。
対処: そのコマンドだけを sudoers で NOPASSWD 指定する(対象は絶対パスで限定)。
sudo visudo -f /etc/sudoers.d/deploy
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx
症状: 3 incorrect password attempts
原因: パスワードを 3 回間違えた。sudo は 3 回失敗で試行を打ち切る。
確認: 入力しているのが root のパスワードではなく自分のパスワード かを確認する。sudo は自分のパスワードを要求する。
対処: もう一度 sudo を実行して自分のパスワードを入力する。忘れた場合は別の管理者に sudo passwd alice でリセットしてもらう。
作業完了チェックリスト
- [ ] 1 コマンドだけなら
sudo command、複数操作ならsudo -iを選べた - [ ] root シェルでの作業後、
exitで抜けた - [ ]
sudoersの編集はvisudo経由で行った - [ ]
NOPASSWDを書く場合、対象コマンドを絶対パスで限定した - [ ]
sudo -lで自分に許可されている操作を確認した