Linux Sudoersの堅牢化:「全員にroot権限」で本番環境を崩壊させないために

Security tutorial - IT technology blog
Security tutorial - IT technology blog

午前2時の悪夢:デフォルトのSudoがリスクになる理由

火曜日の午前2時14分、PagerDutyのアラートが鳴り響きました。主要なWebサーバーの1つが、全トラフィックに対して500エラーを返していました。私は眠い目をこすりながらログインし、データベース의 クラッシュや単純なメモリリークを予想していました。しかし、そこにあったのはもぬけの殻となったサーバーでした。

本番環境のフロントエンド8.4GBを収容していた/var/www/htmlディレクトリが、完全に空になっていたのです。一人のジュニアデベロッパーが、たった一つのCSSファイルのパーミッション問題を解決しようとして、誤ってroot権限で再帰的削除を実行してしまったのでした。彼らの唯一のミスは、デフォルトのsudoグループに所属していたことでした。

新しいVPSで1時間に1,200回ものSSHログイン試行の失敗を目の当たりにして以来、私は外部セキュリティを優先することを学びました。しかし、あの夜、脅威は必ずしもハッカーとは限らないということを思い知らされました。多くの場合、リスクは権限を与えすぎた善意の同僚なのです。ALL=(ALL:ALL) ALLアクセスを安易に付与することは、単なる怠慢なエンジニアリングではなく、システム全体の全消去を招く招待状のようなものです。

Linuxのエコシステムを保護するためには、「rootか、それ以外か」という二元的な考え方から脱却する必要があります。私たちに必要なのは「最小権限の原則(PoLP)」です。/etc/sudoersファイルを正しく使用することで、ユーザーが業務に必要な特定のコマンドのみを実行できるように制限できます。それ以上でもそれ以下でもありません。

Sudoersエントリの構造

設定ファイルの詳細に入る前に、構文を理解する必要があります。多くの管理者はデフォルトのrootエントリを見て、それを新しい採用者のためにコピー&ペーストするだけです。これは大きな見落としです。標準的な設定行を分解してみましょう:

root    ALL=(ALL:ALL) ALL
  • User(ユーザー): 最初のフィールド(root)は対象となるユーザーまたはグループです。グループは常に%で始まります(例:%sudo)。
  • Hosts(ホスト): 最初のALLは、このルールが適用されるホストを定義します。シングルサーバー構成では、これは常にALLになります。ただし、LDAPを使用したネットワーク環境では、ルールを特定の物理マシンに制限できます。
  • Run-as User/Group(実行ユーザー/グループ): (ALL:ALL)セグメントは、ユーザーが誰になりすますことができるかを定義します。最初の部分はユーザー、2番目の部分はグループです。
  • Commands(コマンド): 最後のALLはバイナリへのパスです。これは設定の中で最も危険な変数です。

黄金律:/etc/sudoers を直接編集してはいけない

/etc/sudoers内のセミコロンを一つ打ち間違えるだけで、rootアクセスから完全にロックアウトされる可能性があります。そうなれば、唯一の復旧手段はシングルユーザーモードへの物理的な再起動か、リカバリISOからドライブをマウントすることになるかもしれません。必ずvisudoコマンドを使用してください。これはファイルをバッファで開き、変更が実際のシステムに適用される前に構文チェックを実行します。

sudo visudo

構文を間違えた場合、visudoは「What now?(次は何をしますか?)」というプロンプトで停止します。eキーを押して編集に戻り、エラーを修正してください。壊れたファイルを保存してはいけません。

実践:きめ細かな制御

現実的なシナリオを考えてみましょう。Nginxサービスの管理とログの確認が必要な「alex」というデベロッパーがいるとします。Alexは新しいソフトウェアのインストール、ネットワーク設定の編集、あるいはデータベースの操作を行うべきではありません。

ステップ1:コマンドエイリアスの定義

エイリアスを使用すると、sudoersファイルの可読性が高まります。パスを繰り返し記述するのではなく、ファイルの先頭で論理的にグループ化します。これにより、後で入力ミスが発生する可能性を減らすことができます。

# コマンドエイリアス
Cmnd_Alias WEB_MGMT = /usr/bin/systemctl restart nginx, /usr/bin/systemctl reload nginx, /usr/bin/systemctl status nginx
Cmnd_Alias LOGS = /usr/bin/tail -f /var/log/nginx/*, /usr/bin/journalctl -u nginx

ステップ2:権限の割り当て

次に、これらのエイリアスをAlexに割り当てます。Alexのワークフローを迅速に保つために、これらの特定のコマンドをパスワードなしで実行できるようにしますが、スコープは厳密に制限します。

alex ALL=(root) NOPASSWD: WEB_MGMT, LOGS

(root)を指定することで、Alexがこれらをrootユーザーとして実行することに制限します。もしAlexがsudo systemctl stop sshdを実行しようとしても、システムは断固としてその要求を拒否します。

NOPASSWDの罠

NOPASSWDタグは諸刃の剣です。パスワード入力の手間を省き、自動化に役立ちますが、大きな穴も作ります。もしAlexのアカウントがSSHキーの盗難などで侵害された場合、攻撃者は即座にそれらの特定のコマンドに対するroot権限を手に入れることになります。

vimfindpythonのような「危険な」バイナリにNOPASSWDを使用してはいけません。多くのツールには、アプリ内からrootシェルに移行できる「シェルエスケープ」機能があります。例えば、viへのsudoアクセス権を持つユーザーは、エディタ内で:!/bin/bashと入力するだけでrootになれてしまいます。それほど簡単なことなのです。

NOEXECによるシェルエスケープの防止

エディタやシェル実行機能を持つツールへのアクセスを許可する必要がある場合は、NOEXECタグを使用してください。これにより、コマンドがシェルなどの子プロセスを生成するのを防ぎます。

# シェルエスケープを許可せずに、特定の構成ファイルの編集のみをユーザーに許可する
%junior_devs ALL=(ALL) NOEXEC: /usr/bin/vi /etc/nginx/sites-available/*

「実行ユーザー」の制限

多くの場合、デベロッパーはwww-datadeployなどのアプリケーションユーザーを管理するだけで十分です。実際にはrootである必要はありません。rootアカウントに触れられないように、sudoアクセスを制限できます。

# 'deployer' が 'www-data' としてのみコマンドを実行できるようにする
deployer ALL=(www-data) ALL

これを使用するには、デプロイヤーは対象のユーザーを指定する必要があります:

sudo -u www-data git pull origin main

Sudo使用状況の監査とログ記録

セキュリティとは単なる予防策ではなく、説明責任でもあります。午前2時に何かが壊れたとき、私が最初に確認するのはsudoのログです。デフォルトでは、ほとんどのLinuxディストリビューションはこれらの試行を/var/log/auth.logまたは/var/log/secureに記録します。

ログを堅牢化することで、これをさらに一歩進めることができます。sudoにカスタムファイルへのログ出力を強制したり、セッションの全I/Oを記録したりすることも可能です。ただし、完全なI/O記録は負荷の高いサーバーではかなりのディスク容量を消費する可能性があることに注意してください。

# visudoを使用して /etc/sudoers に追加
Defaults logfile="/var/log/sudo.log"
Defaults log_year, log_host

sudo経由で実行されたすべてのコマンドにはタイムスタンプが付与され、専用のファイルに記録されます。これにより、事後のフォレンジック(原因調査)が非常にスムーズになります。

結論

/etc/sudoersの設定は、それがあなたの仕事を救ってくれる瞬間まで、面倒に感じられるものです。広範な権限をデフォルトにすることは、惨事への近道です。30分かけてCmnd_Aliasグループを定義し、アクセスを最小限に抑えることで、不注意なミスと悪意の両方に対して耐性のあるシステムを構築できます。

次にサーバーをセットアップするときは、単にユーザーをsudoグループに放り込むのではなく、彼らが実際に何をすべきかを考えてください。visudoを使用し、エイリアスを活用し、いつか誰かが最悪のタイミングで間違ったコマンドを打つことを想定しておきましょう。将来の「午前2時のあなた」が、今のあなたに感謝することになるはずです。

Share: