連載
» 2003年11月05日 00時00分 UPDATE

止められないUNIXサーバのセキュリティ対策(5):サービスをセキュアにするための利用制限(3)〜管理者権限の制限のためのsuとsudoの基本〜

[木村靖,三井物産GTI]
※ご注意
本稿の内容を検証する場合は、必ず影響を及ぼさない限られた環境下で行って下さい。また、本稿を利用した行為による問題に関しましては、筆者および株式会社アットマーク・アイティは一切責任を負いかねます。ご了承ください。

 前回は、すべてのコマンドが使用できてしまう特権ユーザー(スーパーユー ザー)の利用制限について説明した。今回は、引き続き特権ユーザーが通常行うsuのセキュリティ上の問題点やsudoの基本的な使い方について紹介する。

suの問題点

 suコマンドは、再ログインになしにrootに限らず任意のユーザーにスイッチすることができるという、とても便利なコマンドだ。しかし、そんなsuコマンドには、以下に示すようなことが懸念されている。

●rootのパスワードを入力する必要がある

 suコマンドは、実行時にスイッチするユーザーのパスワードを入力する必要がある。例えばtelnetでリモートログイン*1してsu rootした場合、当然のことながらネットワーク上にはrootのパスワードが流れてしまうため、万が一盗聴された場合にシステム全体を乗っ取られる可能性も高くなる。また、su rootを実行できるユーザー間でrootのパスワードを共有することになるので、共有する人数が多ければ多いほどrootパスワードの漏えいの危険性も増すことになる。

*1
telnetではなくsshによる暗号化通信を行えば盗聴の危険性も減るが、それでもrootのパスワードがネットワーク上に流れるのは、あまり気持のよいものではない。

●suした後の実行コマンドがログに残らない

 suを実行すると任意のユーザー権限でシェルを実行するが、シェルを実行した後の各コマンドの実行履歴がログに残らない。例えば、いつだれがroot権限でそのコマンドを実行したのかが特定できない。*2

*2
アカウンティング機能を使えばある程度は残せる。アカウンティング機能については次回説明する。

●コマンド単位で権限を制限できない

 suコマンドは、特定コマンドのみsuの実行を許したり、禁止したりすることができない。例えばsu rootすると、スイッチしたrootユーザーのシェル権限が与えられ、その上で実行するすべてのコマンドがroot権限で動作することになる。

 以上のようなsuコマンドで懸念されている点を改善するため、本稿ではsudoを使った管理者特権の利用制限について説明する。

sudoを使う

sudoとは

 sudo(superuser do)は、あるユーザーが別のユーザーとしてコマンドを実行できるようにするためのコマンドだ。先述のsuコマンドと目的は同じだが、セキュリティ面ではsudoの方がより強化されている。

sudoのインストール

 sudoのメインページ(http://www.courtesan.com/sudo/)やミラーサイトからsudoのソースやRPM版などをダウンロードしインストールする(ファイルの整合性チェックも忘れず行うこと)。 portsやpkgsrcの場合はsecurity/sudoからインストールする。

 なお、sudoのバージョン1.6.5p2までにはセキュリティホールが含まれているので最新版を入手すること。以下はソースからコンパイルする一例だ。

% gunzip -cd < sudo-1.6.7p5.tar.gz | tar xvf -
% cd sudo-1.6.7p5
% ./configure
% make
# make install

 コンパイルで手間どうことはないだろうが、詳細については展開先のINSTALLファイルを参照するとよいだろう。

sudoの基本的な使い方

 インストールが完了したら、あとは実際にsudoコマンドを使ってみる。sudoコマンドの書式を以下に示す。

sudoコマンドの書式
sudo[オプション]コマンド

sudoコマンドの主なオプション 指定する内容
-l 現在の設定状況を表示
-L sudoのデフォルト設定値(変数)を表示
-u user|#uid コマンドの実行ユーザー名もしくはUIDを指定する。省略した場合rootが仮定される
-s シェルを実行する。suと同じような形式

 ここで説明した以外にもいくつかオプションがあるので、man sudoで確認しておくとよいだろう。

 基本的な使い方を覚えたらあとは実際に使うだけだが、デフォルトの設定では一般ユーザーはsudoを利用できない。例えば、以下のようなrootしか読めないファイル(/var/log/secure)をsudoを使って読もうとすると、拒否メッセージが表示され、管理者あてにメールが届くことになる(デフォルト)。

% ls -l /var/log/secure
-rw-------  1 root  wheel  0 Apr  8  2003 /var/log/secure

 sudoコマンド実行拒否の様子

% sudo less /var/log/secure 
We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these two things:  
 #1) Respect the privacy of others.
 #2) Think before you type. 
Password: kimuのパスワードを入力
kimu is not in the sudoers file. This incident will be reported.

 また、拒否メッセージと同時に、rootあてに以下のようなメールも届く。

From: kimu
To: root
Subject: *** SECURITY information for atmarkit.example.co.jp ***
atmarkit.example.co.jp : Oct 8 03:35:19 : kimu : user NOT in sudoers 
; TTY=ttyp7 ; PWD=/home/kimu ; USER=root ; COMMAND=/usr/bin/less /var/log/secure

 さらには、sudoで実行した結果は、ログ(/var/log/messagesなど)にも記録される。

Oct 8 03:35:19: atmarkit sudo: kimu 
: TTY=ttyp7 ; PWD=/home/kimu ; USER=root ; COMMAND=/usr/bin/less /var/log/secure

 ご覧いただいたとおり、デフォルトの設定ではroot以外だれもsudoを使えない状態なので、次に示す設定が必要になる。

最初に行うべき設定

 デフォルトではroot以外はsudoを使えない。そのため、最初に基本的な設定から行う。例えばsuで行ったように、wheelグループに属するユーザーに対してsudoの利用権限を与えるように設定を変更してみる。

 sudoの設定は、sudoersファイルで行う。そしてsudoersファイルを編集するには、viなどのエディタで直接編集するのではなく、sudoのメンテナンスコマンドであるvisudoコマンドを使うようにする。

# visudo

  visudoは、sudoersファイルのロックや構文チェック*3なども行ってくれる便利なコマンドで、ファイルの編集には、環境変数のEDITOR にセットされているエディタが使用される。

*3

sudoersファイルの記述を間違えると以下のようなエラーが表示され、sudoersを再編集するどうかを聞かれる。

>>> sudoers file: syntax error, line 28 <<<

What now?

“What now?” に対してeを入力すると編集モードに戻る。


 wheelグループを許可する設定は、あらかじめコメントアウト(先頭に#が付加)されているだけなので、以下に示すとおり行頭の#を取り除いて保存、終了すればよい。

%wheel ALL=(ALL) ALL

 wheelグループにkimuを追加し、もう一度同じようにsudoを試してみる。

% sudo less /var/log/secure
Password: kimuのパスワードを入力

  正しく設定されていれば、lessで/var/log/secureファイルの中身を読むことができるはずだ。

 さて、ここまでで気付いたかもしれないが、冒頭に述べたsuコマンドで懸念されていた点が、2つほどクリアされていることが分かる。

1.rootパスワードの不要

su rootを実行する場合は、rootのパスワードが必要になるが、sudoでは、sudoを実行したユーザーのパスワードさえ分かっていればよいので、各ユーザー間でrootのパスワードを共有する必要がなくなる。su rootを実行する場合は、rootのパスワードが必要になるが、sudoでは、sudoを実行したユーザーのパスワードさえ分かっていればよいので、各ユーザー間でrootのパスワードを共有する必要がなくなる。

2.実行したコマンドの履歴保存

sudoで実行したコマンドの履歴はログファイル(syslog)に記録される。

Oct 8 03:35:19: atmarkit sudo: kimu : TTY=ttyp7 ; PWD=/home/kimu ; USER=root ; COMMAND=/usr/bin/less /var/log/secure

上記の例では、ユーザーkimuがターミナルttyp7からlessコマンドで/var/log/secureファイルを参照した結果だ。PWDはどのディレクトリ上からコマンドを実行したか、USERはどのユーザー権限でコマンドを実行したのかが記録される。

ただし、ログへの保存はsudoが実行されるたびに行われるが、sudo -sやsudo suでシェル権限を取得し、その上で実行されるコマンドについては記録されないことに注意する必要がある。

 残りの1つ(コマンド単位で権限を制限)については、次で説明する。

詳細な設定を行うために

 sudoを有効活用するためには、提供されている機能の仕組みと構文を理解しておく必要がある。

●エイリアス(別名)機能

 sudoersには、次の4タイプのエイリアスを定義できる。

エイリアスタイプ 用途
User_Alias ユーザー名の別名を定義する
Runas_Alias 実行ユーザー名の別名を定義する
Host_Alias 接続元ホストの別名を定義する
Cmnd_Alias 実行するコマンドの別名を定義する

 例えば、User_Aliasを使うことで、複数のユーザーをある1つの名前としてグループ化させることができる。各エイリアスの書式は以下のとおりとなる。

User_Alias NAME = User_List [: NAME = User_List]……
Runas_Alias NAME = Runas_List [: NAME = Runas_List]……
Host_Alias NAME = Host_List [: NAME = Host_List]……
Cmnd_Alias NAME = Cmnd_List [: NAME = Cmnd_List]……

 エイリアスタイプや定義エイリアス(NAME)は、大文字のA-Z、数字、アンダーバー(_)を使用する。そして先頭文字は必ずA〜Zで始まる必要がある。

 以下に各エイリアスの使用例を示す。

User_Alias   WEBMASTER = kimu, yasu, foobar
Runas_Alias  OP = root, operator
Host_Alias   INTERNAL = 192.168.0.0/24
Host_Alias   EXTERNAL = 172.16.0.1, 172.16.0.10
Cmnd_Alias   DUMPS = /bin/mt, /sbin/dump, /sbin/rdump, \                      /sbin/restore, /sbin/rrestore
Cmnd_Alias   SHUTDOWN = /sbin/halt, /sbin/shutdown, /sbin/poweroff, \
                        /sbin/reboot, /sbin/fastboot, /sbin/init

 1行目のUser_Aliasでは、エイリアス名WEBMASTERに、それぞれkimu、yasu、foobarの3つのユーザー名を割り当てている。

 2行目のRunas_Aliasでは、エイリアス名OPに、rootおよびoperatorというコマンドの実行ユーザーを割り当てている。

 3、4行目のHost_Aliasでは、エイリアス名INTERNALに192.168.0.0/24というネットワークを、エイリアス名EXTERNALに172.16.0.1および172.16.0.10というIPアドレスを持つホストをそれぞれ割り当てている。

 5、6行目のCmnd_Aliasでは、エイリアス名DUMPSにバックアップを採取するために必要なコマンド群(/bin/mt、/sbin/dumpなど)を割り当て、エイリアス名SHUTDOWNにOSを起動・停止するために必要なコマンド群を割り当てている。

●制限対象ユーザーの定義

 特定ユーザーやグループ、さらには前述のUser_Aliasで指定した内容を基に、sudoで利用できるユーザー、接続元ホスト、コマンドなどを制限する。書式は以下のとおりとなる。

User_Spec  User_List Host_List = (Runas_List) (NOPASSWD: | PASSWD:)? Cmnd_List

 “?” が付加されている項目は、省略可能であることを意味している。

 以下に前述のエイリアスも含めた利用制限の簡単な例を示す。

Host_Alias INTERNAL = 192.168.0.0/24
Cmnd_Alias REBOOT = /sbin/reboot
kimu ALL = (ALL) ALL
%wheel ALL = (ALL) ALL
yasu ALL = (www) /usr/bin/su
foobar INTERNAL = (root) REBOOT

 1、2行目は、先述のエイリアスの説明で、制限対象ユーザーの定義は空行をはさんだ4行目から始まる。

 4行目のユーザーkimuは、すべての接続元(ALL)から、すべてのユー ザー権限((ALL))で、すべてのコマンド(ALL)を実行できる。

 5行目のグループ%wheelも4行目と同様のことを行える。

 6行目のユーザーyasuは、すべての接続元(ALL)から、ユーザーwwwの権限で((www))、コマンド/usr/bin/suのみ実行できる。

 7行目のユーザーfoobarは、INTERNALの接続元から、ユーザーrootの権限で((root))、REBOOTで定義されたコマンド(/sbin/reboot)のみ実行できる。

 以上の使用例から、どういった設定を行うのかを直感的に理解していただけたと思う。このほかのsudoersの設定や詳細については、sudoのオンラインマニュアル(man sudoers)で確認してほしい。

特定コマンドの利用制限

 基幹業務サーバともなると、役割に応じて担当者が異なることもある。例えば、バックアップテープ交換の担当者とWeb サーバの起動・停止の担当者が異なるようなケースだ。

 両担当者ともメンテナンスを行うためにはroot権限が必要となるが、セキュリティ上の理由、または操作ミスによる影響範囲を最小限に抑えるために、root権限によるコマンドの実行を特定コマンドのみに限定したい場合がある。そのようなケースにおいて、sudoは非常に重宝する。

 例:ユーザーbackupとユーザーwebadmのroot権限で実行可能なコマンドを制限する。

  • ユーザーbackup:バックアップ操作コマンド(mt)のみrootで実行可能
  • ユーザーwebadm:Webサーバの起動・停止スクリプト(apache.sh)のみrootで実行可能
% sudo visudo

 sudoersに以下の2行を追加する。

backup ALL = (root) /bin/mt
webadm ALL = (root) /etc/rc.d/apache.sh

 設定は保存終了した時点で有効となる。

 例:前述の例に、特定のネットワークから接続してきたユーザーのみ許可するように拡張する。ユーザーbackupは192.168.0.0/24、ユーザーwebadmは192.168.100.0/24 からのみに限定する。

% sudo visudo

 sudoersに以下を追加(修正)する。

Host_Alias NET1 = 192.168.0.0/24
Host_Alias NET2 = 192.168.100.0/24
backup NET1 = (root) /bin/mt
webadm NET2 = (root) /etc/rc.d/apache.sh

 以上、実際の運用ともなると、もう少し細かな調整が必要になるが、やるべきことは理解していただけたと思う。

ありがちなミスを防ぐ

 最後に、sudo を使う上で、よくやってしまいがちなミスをなくすための設定を紹介しておく。その代表的な例として、OSの起動・停止コマンドをsudoから実行できないようにする設定である。これにより、操作ミスでうっかりサーバを再起動してしまったということがなくなる。

 例:OSを起動・停止するコマンドの実行のみ禁止する。それ以外は許可。

% sudo visudo

 sudoers に以下を追加する。

Cmnd_Alias SHUTDOWN =  /sbin/halt, /sbin/shutdown, /sbin/poweroff, \                        /sbin/reboot, /sbin/fastboot, /sbin/init
root    ALL=(ALL) ALL, !SHUTDOWN
%wheel  ALL=(ALL) ALL, !SHUTDOWN

 Cmnd_AliasでSHUTDOWNを定義し、OSの起動・停止に関するコマンドを グループ化する。後はグループ化したSHUTDOWNをsudoで実行できないように設定するだけだ。その場合、SHUTDOWNの先頭に!を付加して“否定”にする必要がある。設定後、実際にSHUTDOWNで定義されたコマンドを実行しようとすると、以下のような拒否メッセージが表示され実行できなくなる。

% sudo  reboot
    Sorry, user kimu is not allowed to execute  '/sbin/reboot' 
    as root on atmarkit.example.co.jp.

 OS起動・停止コマンド以外にも、実運用に影響を与えてしまいそうなコマンドは、sudoで気軽に実行できないように制限することをお勧めする。特に簡単に止めることのできない基幹系のサーバならなおさらだ。

 それらのコマンドを使う場合は、sudo -sやsudo suでシェル権限を得てから、ワンクッションおいてから慎重に実行するとよいだろう。

コラム sudoのパスワードキャッシュとパスワードプロンプト

sudoでは一度入力されたパスワードをターミナルごとにキャッシュする。デフォルトでは5分間有効となり、キャッシュタイムアウトはsudoを実行するたびに更新される。

この機能は非常に便利だが、パスワードの入力なしに連続してsudoを実行できるため、root権限でコマンドを実行する際に重要となる“慎重さ”を欠いてしまう。そのため、特に重要なサーバの場合はキャッシュを利用せず、sudo実行時に毎回パスワードを聞くような設定(timestamp_timeout = 0)をsudoersに記述しておくとよいだろう。

Defaults timestamp_timeout = 0

また、“慎重さ”をさらに持たせたいのであれば、sudoのパスワードプロンプトも変更することをお勧めする。sudoを実行した際のパスワードプロンプトは、

Password:

のようなシンプルなものだが、これにsudoを実行したユーザー名(%u)やホスト名(%h)などを明示することで、sudoコマンド実行者に、どのサーバ上でどのユーザーから実行しようとしているのかを再認識させることができる。

sudoのパスワードプロンプトを変更する場合は、sudoresに例えば以下のように記述する。

Defaults passprompt = "%u@%h Password: "

設定を保存すると、「kimu@atmarkit Password:」のようなパスワードプロンプトに変更される。

なお、このほかDefaultsで設定変更可能な内容は、sudo -Lかman sudoersで確認するとよいだろう。


筆者紹介

三井物産GTI (現:三井物産セキュアディレクション株式会社

木村靖



Copyright© 2017 ITmedia, Inc. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

Focus

- PR -

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。