sudoの進化:Unixのsuから現代の権限管理まで
sudoの歴史を、Unixのsuから現代のdoas、polkit、run0まで辿ります。セキュリティ上の落とし穴とベストプラクティスも解説します。

多くの人が驚く事実があります。sudoでパスワードを入力するとき、何のフィードバックも表示されないんです。アスタリスクもドットも何もなく、カーソルが止まったままになります。この設計判断は1980年代になされ、以来40年以上にわたってユーザーを混乱させてきました。端末がフリーズしたと思ってパスワードを何度も打ち直したり、何かが壊れていると思い込んだりするのは日常茶飯事です。Ubuntuはついに、デフォルトでアスタリスクを表示する方向に舵を切りました。46年続いた「無言でパスワードを入力する」伝統に終止符が打たれたわけです。
この小さな変更が、もっと大きな事実を物語っています。Linuxにおける権限昇格の仕組みは、何十年にもわたる判断が寄せ集まったパッチワークのようなものです。見事な判断もあれば、かなり疑わしい判断もあり、そのすべてが後方互換性という重荷を背負っています。ここに至った経緯を理解しておくと、今日のセキュリティ判断もずっと良くなります。
sudo以前:suの時代
Unixにおける最初期の権限昇格ツールはsuでした。「substitute user(ユーザーの切り替え)」の略です。やることはただ一つ、シェルセッション全体を別のユーザー、通常はrootに切り替えることです。suと入力し、rootのパスワードを入力して管理作業をこなし、通常のアカウントに戻るために終了します。
$ su
Password: [type root's password]
# whoami
root
# apt install nginx
# exit
$ whoami
normaluser
suの問題は、Unixシステムが少数の信頼できる運用者の手を離れて大きくなるにつれて明らかになりました。管理者権限が必要な人全員がrootのパスワードを知っている必要がありました。メンバーが辞めたら、rootパスワードを変更して新しいものを他の全員に配り直さなければなりません。監査証跡もありませんでした。一度rootになってしまえば、すべての操作は「root」として記録され、誰が何を実行したのかは分かりませんでした。さらにsuはrootのフルシェルを渡すため、ちょっとしたタイプミスでシステムが吹き飛ぶ可能性がありました。
定番の怖い話があります。管理者がrm -rf /tmp/old_filesと打つつもりが、rm -rf /の後でEnterを押してしまった。フルのrootシェルでは、そのコマンドを止めるものは何もありません。suは「nginxを再起動したい人」と「システム全体への無制限のアクセスが必要な人」を区別しなかったのです。
sudoによるrootパスワード問題の解決
sudo(「superuser do」)は1980年、SUNY BuffaloのBob CoggeshallとCliff Spencerによって作られました。核心となった発想はシンプルですが、大きな変化をもたらしました。rootパスワードを共有する代わりに、個々のユーザーが自分のパスワードを使って特定のコマンドをrootとして実行できるようにしたのです。どのユーザーが何を実行できるかは、システム管理者が設定ファイルで制御します。
これにより、いくつかの問題が一度に解決しました。
- 共有rootパスワードが不要。 各ユーザーは自分の認証情報で認証します。メンバーが辞めたら、そのユーザーのsudo権限を削除するだけです。パスワードのローテーションは不要です。
- 細かい権限設定。 開発者に、フルのroot権限を与えることなく特定のサービスの再起動だけを許可できます。
- 監査証跡。 すべてのsudoコマンドは、実行したユーザー名、実行内容、実行日時とともに記録されます。
- 一時的な権限昇格。 無期限のrootシェルの代わりに、sudoは昇格した権限で1つのコマンドだけを実行し、その後は通常の権限に戻ります。
# Run a single command as root
$ sudo apt install nginx
[sudo] password for priya:
# That's YOUR password, not root's
# The audit trail in /var/log/auth.log:
# Mar 20 14:23:01 web-03 sudo: priya : TTY=pts/0 ;
# PWD=/home/priya ; USER=root ; COMMAND=/usr/bin/apt install nginx
sudoersファイル:強力で危険
sudoの設定は/etc/sudoersにあり、その文法はLinuxの運用の中でも本当に最も分かりにくいものの一つです。文法エラーが一つあるだけでsudoから完全に締め出されることもあります。そのためvisudoコマンドが存在するわけです。保存前にファイルを検証してくれます。
# /etc/sudoers syntax:
# WHO WHERE = (AS_WHOM) WHAT
# Let priya run anything as root on any host
priya ALL=(ALL:ALL) ALL
# Let the 'webdev' group restart nginx only
%webdev ALL=(root) /usr/bin/systemctl restart nginx,\
/usr/bin/systemctl reload nginx
# Let deploy user run deploys without a password
deploy ALL=(root) NOPASSWD: /opt/deploy/run.sh
# DANGEROUS: This looks restrictive but isn't
bob ALL=(root) /usr/bin/vim
# Bob can now run: sudo vim, then :!bash to get a root shell
最後の例、つまり誰かにvimへのsudoアクセスを与えるケースは、人々が常に引っかかるセキュリティの落とし穴です。Vim(やその他多くのプログラム)はシェルコマンドを起動できます。ユーザーがsudo vimを実行できるなら、事実上無制限のroot権限を持つことになります。同じことはless、man、awk、find、pythonなど、他にも数十のコマンドに当てはまります。GTFOBinsプロジェクトは、制限されたシェルから脱出するために使えるバイナリの包括的な一覧を管理しています。
sudoの癖とセキュリティの落とし穴
sudoは40年以上の歴史の中で、本当に奇妙な振る舞いをいくつも蓄積してきました。セキュリティの観点から、これらの癖を理解しておくことは重要です。
- 認証情報のキャッシュ。 パスワードを入力すると、sudoはデフォルトで15分間それをキャッシュします。その間、どのsudoコマンドも認証なしで実行されます。ロック解除したままの端末から離れると、最長15分間は誰でもsudoコマンドを実行できてしまいます。すぐにキャッシュを消すには
sudo -kを実行してください。 - tty_ticketsの設定。 デフォルトではsudoの認証キャッシュは端末ごとに分かれています。しかし一部のシステムでは、ある端末セッションで認証すると、すべての端末でsudoがロック解除されてしまいます。
Defaultsの設定を確認してください。 - 環境変数。 sudoはほとんどの環境変数を無害化しますが、すべてではありません。
LD_PRELOADとLD_LIBRARY_PATHは除去されますが、env_keepの設定を誤ると、攻撃者が悪意のあるライブラリパスを注入できてしまいます。これは実際の権限昇格エクスプロイトのいくつかの基礎になってきました。 - NOPASSWDの落とし穴。
NOPASSWDは自動化には便利ですが、広く適用しすぎると危険です。NOPASSWDのsudo権限を持つユーザーとして動いている侵害されたアプリケーションは、事実上rootを持つことになります。解読すべきパスワードすら存在しないのです。
# Security hardening for sudoers:
# Require password every time (disable caching)
Defaults timestamp_timeout=0
# Or reduce cache to 1 minute
Defaults timestamp_timeout=1
# Ensure credential cache is per-terminal
Defaults tty_tickets
# Log all sudo I/O (records full terminal sessions)
Defaults log_input, log_output
Defaults iolog_dir=/var/log/sudo-io
# Require root password instead of user password
# (prevents compromised user accounts from sudo-ing)
Defaults rootpw
# Show asterisks when typing password
Defaults pwfeedback
現代的な代替手段:doas、polkit、run0
sudoの複雑さから、それぞれ異なる思想を持ついくつかの代替ツールが生まれました。
doas:複雑さのないsudo
OpenBSDのdoas(「dedicated OpenBSD application subexecutor」)は、sudoが監査するにはあまりに複雑になったことを受けて、2015年にTed Unangstによって作られました。設定全体は通常2〜3行です。
# /etc/doas.conf — the entire configuration
permit persist priya
permit nopass deploy as root cmd /opt/deploy/run.sh
# That's it. Compare this to a typical sudoers file.
# 'persist' is like sudo's credential caching
# 'nopass' is like NOPASSWD
doasのソースコードは約2,500行のCです。sudoは15万行を超えます。sudoの高度な機能(コマンドごとの引数マッチングやLDAP連携など)が不要な環境では、doasは設定、監査、セキュリティ確保が劇的に簡単です。私は個人のサーバーで何年も使っていますが、sudoが恋しくなったことは一度もありません。
polkit:きめ細かなデスクトップ権限
PolicyKit(polkit)はまったく違うアプローチを取ります。個々のコマンドをラップするのではなく、アプリケーションが要求できるアクションを定義します。デスクトップアプリがネットワーク設定を変更する必要があると、polkitに許可を求め、polkitはそのルールに基づいて許可、拒否、またはユーザーへの確認を決めます。
これがLinuxデスクトップで、パスワードなしでUSBドライブをマウントできる一方で、ソフトウェアのインストールには認証が必要になっている仕組みです。粒度はコマンド単位ではなくアクション単位であり、デスクトップユーザーが実際に権限をどう考えているかに、より合っています。
run0:systemdによる根本的な再設計
systemdのrun0は最も新しい選択肢で、sudoとは根本的に異なる仕組みで動きます。既存のセッションからコマンドをrootとして実行する(setuidビットが必要になり、セキュリティ上の頭痛の種を生む)代わりに、run0はサービスマネージャーにrootとして動く新しいサービスを起動させます。ユーザーのセッションが昇格権限を得ることはなく、特権プロセスは完全に切り離されています。
これにより、sudoの脆弱性のカテゴリ全体を回避できます。setuidバイナリもなく、認証情報のキャッシュもなく、環境変数インジェクションの攻撃面もありません。引き換えとして、systemdが必要になるため、BSDシステムや最小構成のLinuxでは使えません。しかしsystemdベースのサーバーにとっては、間違いなく利用可能な中で最も安全な選択肢と言えるでしょう。
実践的な推奨事項
何年もLinuxサーバーを運用し、権限昇格インシデントを調査してきた経験から、実際に推奨したいことは次のとおりです。
- rootログインを完全に無効化する。 すべてに
sudoまたはdoasを使いましょう。共有のrootパスワードは存在すべきではありません。 - sudoersではユーザー個人ではなくグループを使う。 グループメンバーシップでアクセスを管理しましょう。メンバーが辞めたら、グループから外すだけです。
- インタプリタやエディタにsudo権限を与えない。
sudo vim、sudo python、sudo lessはNGです。root所有のファイルを編集する必要があるなら、代わりにsudoeditを使いましょう。 - NOPASSWDルールは最小限に。 自動化されたプロセスに限定し、フルパスで指定した特定のコマンドにだけ使いましょう。
- sudoのログを有効にする。 最低限、すべてのsudoコマンドを記録しましょう。機密性の高いシステムでは、完全なI/Oログも有効にしてください。
- 単純なシステムではdoasを検討する。 LDAP連携や複雑なマッチングルールが不要なら、doasの方が正しく設定しやすいです。
- 認証キャッシュは積極的に短くする。
timestamp_timeoutを1〜5分に減らすか、本番サーバーではキャッシュを完全に無効化しましょう。
最良の権限昇格の仕組みとは、必要最小限のアクセスを、必要最小限の時間だけ許可し、完全な監査証跡を残すものです。それ以外はすべて妥協です。
sudoがどこかに消えることはありません。スクリプト、自動化、ドキュメント、そして身体に染みついた操作感にあまりに深く組み込まれています。それでも代替手段の状況は、かつてないほど健全になっています。sudoを(適切に強化して)使い続けるにせよ、シンプルさのためにdoasに移行するにせよ、セキュリティ重視のシステムでrun0を採用するにせよ、大事なのは権限昇格ツールが実際に何をしているのかを理解することです。人々がsudoがやると思っていることと実際にやっていることのギャップこそ、ほとんどのセキュリティインシデントが潜んでいる場所だからです。


