System Admins and Developers
Hands-On Labs
このラボでは、アプリケーションとシステムの保護に役立つOracle Solarisのいくつかのセキュリティ機能について簡単に学習します。具体的には、以下のテクノロジーについて説明します。
ラボの演習3および4には、Apache 2.2が必要です。
Apache 2.2をSolaris 11にインストールするには、以下の手順を実行します。



予想される所要時間:20分間
この演習の目標は、SolarisにおけるRBAC/特権のフレームワークを基本的に理解することです。
以下の概要説明について、Joerg MoellenkampとLess known Solaris features: RBAC and Privileges - Part 1: Introductionに関する彼の寄稿に感謝の意を表明します。
rootは以前から存在していました。そして、rootには制限がありませんでした。これは、望ましい状態ではありませんでした。rootは、それ自体が制御の対象となることなく、すべてのものを制御できました。しかし、rootを制御する必要がありました。一般ユーザーとrootを区別するものは、短い文字列だけでした。この特別な文字列を知っていれば、誰でもrootとしてコマンドを実行できました。
ただし、rootは、単独の存在ではありませんでした。rootには、デーモンという複数の従属プログラムがありました。それらのプログラムのいくつかは、日常のジョブを実行するために一般ユーザーが持たない特別な権限を必要としました。しかし、rootは、不可分の存在でした。そのため、従属プログラムは、rootの権限によって動作する必要がありました。とはいえ、従属プログラムは、rootとは異なり完全ではありませんでした。一部の従属プログラムは、一般ユーザーが一定量を超えるコマンドを同時に命令するだけで、一般ユーザーによって命令される動作を何でも実行するようになりました。
UNIXシステムにおける従来の権限は、二面性があります。スーパーユーザーと一般ユーザーです。一般ユーザーはシステムにおいて制限のある一連の権限を持ち、スーパーユーザーは制限のない一連の権限を持ちます。一般ユーザーがシステムを変更するには、直接rootとしてログインするか、rootの権限を取得(su -コマンドを使用)する必要があります。ただし、そのようなユーザーは、システムに無制限にアクセスできます。多くの場合、これは望ましくありません。たとえば、オペレータがシステムで実行しなければならない作業が、ユーザー作成だけである場合、オペレータにシステム変更権限を与える必要があるでしょうか。useraddやpasswdを実行できるようにオペレータをトレーニングしたとします。このオペレータが他のコマンドにも興味を持った場合には、どうすればいいでしょうか。ユーザー作成やパスワード変更にはroot権限が必要です。このオペレータの操作を制限するには、いくつかの手順が必要です。
しかし、問題はこれにとどまりません。プログラムが機能するには、システムを変更する必要があります。その典型的な例が、Webサーバーです。Webサーバーでポート80を使用したいとします。1024より少ない番号のポートは、特権ポートです。ポート80をリスニングするには、システムの構造を変更できる特別な権限が必要です。一般ユーザーには、これらの権限はありません。このため、Webサーバーをrootとして起動する必要があります。このプロセスの子プロセスは、一般ユーザーで実行することにより、rootの権限を失います。しかし、プログラムのこのシングル・インスタンスは、そのユーザーのすべての権限を持ちます。このプロセスは必要以上の権限を持つため、悪意のあるユーザーによる攻撃の手段となる可能性があります。
セキュリティには最小特権という概念があります。ユーザーが割り当てられたタスクを実行するために必要なだけの最小限の特権のみを、そのユーザーに与えることです。現実世界に例えると、学校のすべての部屋に入れるマスター・キーを、C棟の作業しか行わない用務員に渡すことはしません。逆に、緊急事態に備えて、信頼できる一部の職員には、すべての部屋に入れる権限を与えます。
コンピュータのセキュリティにも同じ考え方があります。すべてのユーザーは、そのユーザーのジョブの実行できる、システムにおける最小限の特権のみを持つ必要があります。スーパーユーザーの概念は、すべてかゼロかというモデルであるため、これには適していません。スーパーユーザーの概念では、基本的な特権を持つ一般ユーザーと無制限の権限を持つユーザーが存在し、その中間はありません。これは、最小特権モデルと合致しません。
用務員の鍵は、良い例です。大きな学校を想像してください。配管担当(名前はLennyとCarl)、校庭担当(名前はHomer)、およびセキュリティ・システム担当(名前はMarge、Lennyもときどき手伝います)の各用務員がいるとします。
それぞれ、役割に応じて異なる一連の特権を持ちます。たとえば、配管担当の用務員は、暖房装置のあるすべての部屋に入れます。校庭担当の用務員は、芝刈り機のある車庫にしか入れません。
用務員は、その用務員の仕事を開始するときに、その役割を取得します。特権の観点からは、用務員が誰であるかは重要ではなく、用務員がどの役割を取得しているかが重要です。Lennyは、タイム・カードを押して、それ以降の8時間に及ぶ配管担当の用務員の役割を取得します。そして、Lennyは、その仕事を行っている間、その役割固有の特権を使用します。ただし、Lennyには、事務室や作業場で行う作業もあります。これらは、Lenny用の部屋なので、特別な特権を必要としません。
ロール・ベースのアクセス制御も、この例とよく似ています。ユーザーは、システムにログインして、作業を開始します。このユーザーは、たとえば、自分宛の電子メールを読み(特権は不要)、そのメールの内容が"上司からのユーザー(xy45345)の作成指示 "であることを確認します。ここで、特権が必要になります。このユーザーは、ユーザー管理者のロール(役割)を取得し、ユーザーを作成します。ジョブが完了したら、特権は不要になります。ロールを解除し、一般ユーザーの権限で、上司宛の"作業完了通知"メールを作成します。
つまり、ロール・ベースのアクセス制御とは、ロールを定義し、それらに特権を与えて、ユーザーをこのロールに割り当てることです。
この言葉は、この概要説明で、これまで何度も使用しました。では、特権とは何でしょうか。特権とは、何かを行うための権限です。たとえば、配管担当の用務員が、暖房装置の制御パネルの鍵を持つことです。
UNIXユーザーの場合も同じです。UNIXシステムでは、すべてのユーザーに特権があります。一般ユーザーは、許可される場合に、ファイルを開いたり、閉じたり、読み取ったり、書き込んだり、削除したりする特権を持ちます。許可される場合というのは、ユーザーがファイルを自分で作成した場合、ユーザーがファイルの作成者と同じグループに属している場合、ファイルの作成者がすべてのユーザーにそれらを実行する権限を与えている場合などです。これは当たり前のことのように思えるかもしれませんが、ユーザーがシステムに提示したログイン資格証明に基づく特権です。この一般ユーザーは、システム上のすべてのファイルを読み取ったり、ポート番号1024を使用したりする特権を持ちません。
システム上で行われるすべてのことは、これらの特権に基づいています。Solarisでは、タスクが、多数の特権セットに分割されています。現時点で、70の異なる特権がシステムに存在します。一般ユーザーとの相違は、一般ユーザーが基本特権セットしか持たない点です(一方、rootはすべての特権を持ちます)。
Solarisではモデルが変更されており、特権とユーザーは相互に結び付いていません。どのユーザーにも従来のrootユーザーの権限を与えることができ、rootユーザーの特権を制限することもできます。システムの標準構成がスーパーユーザー・モデルと類似していることを要求するOracleのバイナリ互換性保証により、Solarisは、従来のスーパーユーザー・モデルのように見える構成になっています。アプリケーションによっては、rootユーザーまたはUID 0にのみ無制限の権限があることを前提としており、これ以外のユーザーで起動すると終了する場合があります。
Solarisでは、UID 0がシステム構成ファイルの所有者であり、そのために、システム構成を変更できる点が唯一特別な点です。
どちらの機能も、Trusted Solaris製品から生まれました。Trusted Solarisは、最高水準のセキュリティを保証するSolarisのバージョンでした。現在では、これらのメカニズムが、Trusted Extensionsとの組み合わせにより、通常のSolarisに含まれています。つまり、RBACは、実際には古い機能であり、Solaris 8(2000年に発表)以降のSolarisに組み込まれています。特権は、Solaris 10の最初のリリース(2005年2月)でSolaris全般に組み込まれました。
デスクトップで、背景の任意の場所を右クリックし、ポップアップ・メニューから「Open Terminal」を選択してターミナル・ウィンドウを開きます。

Oracleユーザーに割り当てられているロールを調べましょう。ターミナル・ウィンドウで、以下のコマンドを実行します。
oracle@solaris:~$ roles root
ご覧のように、ロールrootがユーザーに割り当てられているので、rootロールを取得できます。Solaris 11では、rootはユーザーではなくロールです。このため、一般ユーザーとしてシステムにログインしてから、suコマンドを使用してrootロールを取得する必要があります。
ターミナル・ウィンドウで、以下のように入力します。
oracle@solaris:~$ userattr type root role oracle@solaris:~$ auths root solaris.*
ご覧のように、rootは、 すべてのsolaris 認証によってロールとして定義されています。この効果は、従来のrootユーザーと似ています。これは、下位互換性のための措置です。
また、ユーザーにrootロールが割り当てられているため、rootロールを取得することにより、以下の処理を試みることができます。
oracle@solaris:~$ whoami oracle oracle@solaris:~$ su Password: <root password> oracle@solaris:~# whoami root oracle@solaris:~# who am I oracle pts/1 Apr 21 07:32 (:0.0) oracle@solaris:~# exit exit oracle@solaris:~$
Joe Doeという新しいユーザーをシステムに追加しましょう。
oracle@solaris:~$ useradd -d /export/home/jdoe -m -s /bin/ksh -c "Joe Doe" jdoe UX: useradd: ERROR: Permission denied.
ご覧のように、useraddコマンドの使用が許可されません。"root"特権でuseraddを実行するには、suを使用して、足りない権限をアカウントに割り当てる必要があります。suコマンドを実行すると、rootパスワードの入力を求められます。
oracle@solaris:~$ su root -c "usermod -K profiles='User Management' oracle" Password: <your root password> oracle@solaris:~$ userattr profiles oracle User Management
このように、ユーザー管理権限が得られました。この権限を利用するには、プロファイル・シェル(pfbashなど)を起動して、新しいユーザー(jdoe)を作成します。
oracle@solaris:~$ pfbash oracle@solaris:~$ useradd -d /export/home/jdoe -g oinstall -m -s /bin/ksh -c "Joe Doe" jdoe
ユーザーのパスワードを変更するには、User Securityプロファイルが割り当てられている必要がありますが、このプロファイルを通常のユーザーに割り当てることは推奨されません。これは、そのユーザーが、より権限のあるユーザーを含む他のユーザーのパスワードを変更できるようになるためです。User Managementプロファイルは、すでに持っているものを委任することしかできないため安全です。それでは、rootロールを使用して新しいユーザーのパスワードを変更しましょう。
oracle@solaris:~$ su root -c passwd jdoe Password: <root password> New Password: abc123 Re-enter new Password: abc123 passwd: password successfully changed for jdoe oracle@solaris:~$ su - jdoe Password: abc123 Oracle Corporation SunOS 5.11 11.0 November 2011 jdoe@solaris:/export/home/jdoe$ roles No roles jdoe@solaris:/export/home/jdoe$ su root Password: <root password> Roles can only be assumed by authorized users su: Sorry jdoe@solaris:/export/home/jdoe$ exit oracle@solaris:~$
注:-g oinstallオプションがuseraddコマンドに使用されています。これを加える必要があるのは、oracleユーザーが、このラボのセットアップでは、デフォルトでoinstallグループに含まれているためです。Oracle Solaris 11におけるデフォルト・グループは、staffです。このため、-g oinstallによってユーザーをoinstallグループに追加することを明示的に要求しないでuseraddを実行すると、新しいユーザーをstaffグループへ追加しようとします。この操作は、oracleユーザーでは許可されません。これは、"User Management"プロファイルを持つユーザーが、そのユーザーのすでに属しているグループにしか新しいユーザーを追加できないためです。
Solaris 11では、ロール認証の手順が変更されました。古いバージョンのSolaris(Oracle Solaris 11 Expressを含む)を実行している場合は、ロールを取得するためにロール・パスワードを知っている必要があります。Oracle Solaris 11では、ユーザーが特定のロールを取得する場合にロール・パスワードまたはユーザー・パスワードのどちらを使用するかを指定することができます。 管理者は、'roleauth'キーワードについて'user'または'role'を指定できます。roleauthを指定しない場合は、'role'が指定されます。デフォルトでは、新しく作成されるすべてのロールが'user'になります。
ご覧のように、jdoeにはロールが割り当てられておらず、このユーザーはsuを使用してrootロールを取得することができません。このユーザーについては、後で説明します。では、演習2で、特権の詳細について学習しましょう。
予想される所要時間:20分間
この演習の目的は、Solarisの特権とそれらの使用方法を理解することです。
特権とは、カーネルで操作を実行するための権限です。これらの権限は、カーネルによって設定されます。カーネル内で何かを行う場合は、常に、アクセスが特権によって制御されます。
contract_event、contract_identity、contract_observer、cpc_cpu、dtrace_kernel、dtrace_proc、dtrace_user、file_chown、file_chown_self、file_dac_execute、file_dac_read、file_dac_search、file_dac_write、file_downgrade_sl、file_flag_set、file_link_any、file_owner、file_setid、file_upgrade_sl、graphics_access、graphics_map、ipc_dac_read、ipc_dac_write、ipc_owner、net_access、net_bindmlp、net_icmpaccess、net_mac_aware、net_mac_implicit、net_observability、net_privaddr、net_rawaccess、proc_audit、proc_chroot、proc_clock_highres、proc_exec、proc_fork、proc_info、proc_lock_memory、proc_owner、proc_priocntl、proc_session、proc_setid、proc_taskid、proc_zone、sys_acct、sys_admin、sys_audit、sys_config、sys_devices、sys_ipc_config、sys_linkdir、sys_mount、sys_iptun_config、sys_dl_config、sys_ip_config、sys_net_config、sys_nfs、sys_ppp_config、sys_res_config、sys_resource、sys_smb、sys_suser_compat、sys_time、sys_trans_label、virt_manage、win_colormap、win_config、win_dac_read、win_dac_write、win_devices、win_dga、win_downgrade_sl、win_fontpath、win_mac_read、win_mac_write、win_selection、win_upgrade_sl、xvm_control
凡例:青色 - 基本特権
従来のUNIXシステムにはrootユーザーがあり、このユーザーがすべての特権を持っています。そして、制限された特権セットを持つ一般ユーザーがあります。一部のタスクは、場合により、実行するために管理者特権が必要です。ただし、システムを管理する必要まではありません。
oracle@solaris:~$ ls -l /usr/sbin/traceroute -r-sr-xr-x 1 root bin 46868 2010-11-05 08:02 /usr/sbin/traceroute oracle@solaris:~$ ls -l /usr/sbin/ping -r-sr-xr-x 1 root bin 55940 2010-11-05 08:01 /usr/sbin/ping
tracerouteとpingは、どちらもsetuidツールであるため、使用できます。setuidにより、特定のユーザーIDとそのユーザーが持つすべての特権によってプロセスを実行できるようになります。rootに対するsetuidの場合、そのプロセスはrootの特権を持ちます。Solarisのsetuidプログラムは、特権を認識し、その操作に必要な特権だけを保持することができます。
pingには特殊な特権(ICMPへのアクセスを使用する特権)が必要です。従来のシステムでは、この権限は、rootユーザーのために予約されています。このため、pingプログラムは、rootの権限で実行する必要があります。問題は、このプログラムの実行時に、プログラムがユーザーのすべての権限を持つことです。このプログラムは、ICMPへのアクセスだけでなく、/etcにあるファイルの削除といった、システムでのすべての操作を実行できます。これは、pingまたはtracerouteでは問題にならないかもしれませんが、より大きなプログラムのことを考える必要があります。setuidプログラムを悪用することで、ユーザーの特権をエスカレーションすることができます。
一般ユーザーの特権について考えてみましょう。pprivという、システム内の任意のプロセスの特権を取得するツールがあります。$$は、実際のプロセスID(次の場合はシェルのプロセスID)のショートカットです。
oracle@solaris:~$ ppriv $$
1684: -bash
flags = <none>
E: basic
I: basic
P: basic
L: all
"basic"が示す内容を確認するために、-vをpprivフラグに追加してエイリアスを展開できます。
oracle@solaris:~$ ppriv -v $$
1684: -bash
flags = <none>
E: file_link_any,file_read,file_write,net_access,proc_exec,proc_fork,proc_info,proc_session
I: file_link_any,file_read,file_write,net_access,proc_exec,proc_fork,proc_info,proc_session
P: file_link_any,file_read,file_write,net_access,proc_exec,proc_fork,proc_info,proc_session
L: contract_event,contract_identity,contract_observer,cpc_cpu,dtrace_kernel,dtrace_proc,dtrace_user,file_chown,file_chown_self,file_dac_execute,file_dac_read,file_dac_search,file_dac_write,file_downgrade_sl,file_flag_set,file_link_any,file_owner,file_read,file_setid,file_upgrade_sl,file_write,graphics_access,graphics_map,ipc_dac_read,ipc_dac_write,ipc_owner,net_access,net_bindmlp,net_icmpaccess,net_mac_aware,net_mac_implicit,net_observability,net_privaddr,net_rawaccess,proc_audit,proc_chroot,proc_clock_highres,proc_exec,proc_fork,proc_info,proc_lock_memory,proc_owner,proc_priocntl,proc_session,proc_setid,proc_taskid,proc_zone,sys_acct,sys_admin,sys_audit,sys_config,sys_devices,sys_dl_config,sys_ip_config,sys_ipc_config,sys_iptun_config,sys_linkdir,sys_mount,sys_net_config,sys_nfs,sys_ppp_config,sys_res_bind,sys_res_config,sys_resource,sys_smb,sys_suser_compat,sys_time,sys_trans_label,virt_manage,win_colormap,win_config,win_dac_read,win_dac_write,win_devices,win_dga,win_downgrade_sl,win_fontpath,win_mac_read,win_mac_write,win_selection,win_upgrade_sl,xvm_control
システム内の各プロセスは、プロセスが特権を使用できるかどうかを決定する4つの特権セットを持ちます。特権の理論は、非常に複雑です。各特権セットが他の特権セットを制御する方法または制御される方法を学習する場合は、Oracle Solaris 11セキュリティーサービス開発ガイドの"特権の実装方法"を参照することを推奨します。
ここでは、最初の文字の意味だけを説明します。
特権セットは、鍵束と考えることができます。実効特権セットは、用務員が鍵束として持っている鍵です。許可された特権セットは、用務員が鍵束に加えることができる鍵です。用務員は、一部の鍵を鍵束から取り除くことを判断できます。たとえば、今日は232号室の作業しかしないので、他の鍵はすべて必要ない、と考えるかもしれません。不要な鍵は事務室に置いていきます。この場合、鍵束を紛失しても、この1つの部屋の出入りに問題が生じるだけで、学校全体の問題とはなりません。
継承可能な特権セットは、実際には、鍵束ではありません。用務員が新しい助手について"優れた作業者だが、高価な道具のある部屋の鍵は渡せない"と考えている場合と似ています。制限特権セットは、用務員の上司が班長に対して"助手には、普通の部屋の鍵は渡してもいいが、オラクル製のこの点滅する箱が入っている部屋の鍵は渡してはいけない"という全般的な命令を出す場合と似ています。
現時点では、興味深い特権セットのほとんどがEつまり実効特権セットです。これは、プロセスで効果的に使用できる特権セットです。上記の特権の完全なリストと比べると、この特権セットは非常に少数です。しかし、これは、UNIXシステムを使用する場合の使用経験と一致します。
この点を、rootロールを取得する場合について見てみましょう。
oracle@solaris:~$ su -
Password: <root password>
Oracle Corporation SunOS 5.11 11.0 November 2011
You have new mail.
root@solaris:~# ppriv $$
1779: -bash
flags = <none>
E: all
I: basic
P: all
L: all
このロールは、非常に多くの特権を持っています。実効特権セットは、非常に広範囲です。rootロールを取得する場合は、システムのすべての特権を取得することになります。注:これは、完全に、下位互換性を保持するためのものであり、将来的には使用することが推奨されていません。
一部の特権をjdoeユーザーに追加しましょう。このユーザーはいくつかのアプリケーションをデバッグするためにDTraceにアクセスする必要のあるソフトウェア開発者であると仮定してください。
最初に、jdoeとしてDTraceを使用してみましょう。
# su - jdoe
Password: abc123
Oracle Corporation SunOS 5.11 11.0 November 2011
jdoe@solaris:/export/home/jdoe$ ppriv $$
1790: -ksh
flags = <none>
E: basic
I: basic
P: basic
L: all
jdoe@solaris:/export/home/jdoe$ dtrace -l
dtrace: failed to initialize dtrace: DTrace requires additional privileges
ご覧のように、jdoeには、DTraceの使用するために必要な特権がありません。DTraceを使用するためにユーザーが必要とするものに応じて、DTraceで必要な特権は3つあります(dtrace_kernel、dtrace_proc、dtrace_user)。これらの特権は、以下の3つの異なる方法でユーザーに追加できます。
dtrace特権をユーザーに直接追加する方法を見てみましょう(最初のコマンドをrootとして実行してから、rootシェルを終了し、oracleユーザーとして作業を進めます)。
# usermod -K defaultpriv=basic,dtrace_kernel,dtrace_proc,dtrace_user jdoe oracle@solaris:~$ userattr defaultpriv basic,dtrace_kernel,dtrace_proc,dtrace_user
| 注 :ユーザーに割り当てる特権セットに基本特権を追加する際は、ファイルの作成や新しいプロセスの起動といった基本操作の大半をユーザーが実行できるように追加する必要があります。 |
ここで表示されるように、jdoeは、dtraceコマンドを使用するために必要な3つの特権を持ちました。では、コマンドを実行してみましょう。
oracle@solaris:~$ su - jdoe
Password: abc123
Oracle Corporation SunOS 5.11 11.0 November 2011
jdoe@solaris:/export/home/jdoe$ ppriv $$
1814: -ksh
flags = <none>
E: basic,dtrace_kernel,dtrace_proc,dtrace_user
I: basic,dtrace_kernel,dtrace_proc,dtrace_user
P: basic,dtrace_kernel,dtrace_proc,dtrace_user
L: all
jdoe@solaris:/export/home/jdoe$ dtrace -l | more
ID PROVIDER MODULE FUNCTION NAME
1 dtrace BEGIN
2 dtrace END
3 dtrace ERROR
530 fbt smbsrv smb_match_private entry
...
555 fbt smbsrv smb_gmttoken_xdr return
--More--
正常に実行できたので、試しに同じことを実行するロールも作成してみましょう。
最初に、jdoeからdtrace特権を削除しましょう。
oracle@solaris:~$ usermod -K defaultpriv=basic jdoe oracle@solaris:~$ userattr defaultpriv jdoe basic
次に、rootシェルを使用して(つまりrootユーザーとして)ロールを作成し、このロールに"bugger"という名前を付けてjdoeに割り当てます。
# roleadd -u 201 -d /export/home/bugger -P "Process Management" bugger oracle@solaris:~$ passwd bugger New Password: abc123 Re-enter new Password: abc123 passwd: password successfully changed for bugger oracle@solaris:~$ rolemod -K defaultpriv=basic,dtrace_kernel,dtrace_proc,dtrace_user bugger oracle@solaris:~$ userattr defaultpriv bugger basic,dtrace_kernel,dtrace_proc,dtrace_user oracle@solaris:~$ usermod -R bugger jdoe oracle@solaris:~$ roles jdoe bugger
正常に実行できました。では、jdoeがDTraceを使用できることを確認しましょう。
oracle@solaris:~$ su - jdoe
Password:
Oracle Corporation SunOS 5.11 11.0 November 2011
jdoe@solaris:/export/home/jdoe$ roles
bugger
jdoe@solaris:/export/home/jdoe$ su bugger
Password:
jdoe@solaris:~$ ppriv $$
1885: sh
flags = PRIV_PFEXEC
E: basic,dtrace_kernel,dtrace_proc,dtrace_user
I: basic,dtrace_kernel,dtrace_proc,dtrace_user
P: basic,dtrace_kernel,dtrace_proc,dtrace_user
L: all
jdoe@solaris:~$ dtrace -l | more
ID PROVIDER MODULE FUNCTION NAME
1 dtrace BEGIN
2 dtrace END
3 dtrace ERROR
530 fbt smbsrv smb_match_private entry
...
555 fbt smbsrv smb_gmttoken_xdr return
--More--
以上で、特権とそれらをユーザーに割り当てる方法について基本的に理解できたはずです。ただし、同じことをプロセスに対しても実行できることが望ましいので、この点について演習3で学習しましょう。
予想される所要時間:10分間
特権をユーザーに追加する方法をすでに学習しました。ここでは、特権とプロセスの相互作用について学習します。特権を認識するプロセスと特権を認識しないプロセスの両方について説明します。
特権を管理するという発想は、ユーザーとそのシェルに限定されるものではありません。どのシステムでも、何十ものプログラムがデーモンとして動作しています。
これらのデーモンは、複数の方法で特権と相互に作用します。その最良の方法は、"特権を認識するプログラミング"です。使用しているシステム用のデーモンを作成すると仮定しましょう。たとえば、デーモンがexec()コールを決して実行しないことが分かっているとします。この場合は、この特権を問題なく削除できます。このプロセスは、許可された特権セットを変更します。このプロセスは、特権を削除できますが、追加できません。このため、もし誰かがプロセスにアクセスできたとしても、その攻撃者はexec()コールを実行できません。このプロセスには、そのようなコールを実行する特権もありません。また、攻撃者は、その特権を追加しなおすこともできません。Solaris内の複数のプロセスとプログラムは、すでに特権を認識します。その例としては、カーネル・レベル暗号化フレームワーク・デーモンなどがあります。デーモンの特権について見てみましょう。
特権を監視または管理するには、プロセス自体がすでにそれらの特権を持っている必要があります。このため、以降の演習のためにrootロールを取得します。
oracle@solaris:~$ su - root
Password: <root password>
oracle@solaris:~# ps -ef | grep "kcfd"
daemon 129 1 0 Apr 04 ? 0:00 /lib/crypto/kcfd
oracle 1902 1684 0 08:19:19 pts/1 0:00 grep kcfd
oracle@solaris:~# ppriv -v 129
129: /lib/crypto/kcfd
flags = PRIV_AWARE
E: file_owner,file_read,file_write,net_access,proc_priocntl,sys_devices
I: none
P: file_owner,file_read,file_write,net_access,proc_priocntl,sys_devices
L: none
このデーモンは、一般ユーザーの基本特権も持っていません。このデーモンは、そのジョブを実行するための必要最小限の特権だけを持っています。
しかし、すべてのものが完全ではありません。特権を認識しないプロセスも存在します。したがって、別の方法によって特権を制限する必要があります。ここで、サービス管理機能が役立ちます。以下の例は、Glenn BrunetteのブループリントであるLimiting Service Privileges in the Solaris 10 Operating Systemからコピーしたものです。
Apache Webサーバーを例に取ってみましょう。Apache Webサーバーは、特権を認識しません。サービス管理フレームワーク(SMF)を使用してこのデーモンを起動します。
oracle@solaris:~# svcadm -v enable -s apache22 svc:/network/http:apache22 enabled.
正常に実行できたので、Apacheデーモンのプロセスを調べます。
oracle@solaris:~# ps -ef | grep "apache" | grep -v grep
webservd 1931 1928 0 08:22:59 ? 0:00 /usr/apache2/2.2/bin/httpd -k start
webservd 1934 1928 0 08:22:59 ? 0:00 /usr/apache2/2.2/bin/httpd -k start
webservd 1932 1928 0 08:22:59 ? 0:00 /usr/apache2/2.2/bin/httpd -k start
webservd 1935 1928 0 08:22:59 ? 0:00 /usr/apache2/2.2/bin/httpd -k start
webservd 1933 1928 0 08:22:59 ? 0:00 /usr/apache2/2.2/bin/httpd -k start
root 1928 1 1 08:22:58 ? 0:00 /usr/apache2/2.2/bin/httpd -k start
6つのデーモンがwebservdとして動作し、1つのデーモンがrootとして動作しています。
oracle@solaris:~# ppriv 1928 1928: /usr/apache2/2.2/bin/httpd -k start flags = <none> E: all I: basic P: all L: all
rootプロセスに関しては、予想されるとおり、rootユーザーの完全な特権セットを持っています。その子プロセスの一つについて調べてみましょう。
oracle@solaris:~# ppriv 1931
1931: /usr/apache2/2.2/bin/httpd -k start
flags = <none>
E: basic
I: basic
P: basic
L: all
基本特権しか持っておらず、はるかに望ましい状態です。
さて、この構成には理由があります。UNIXシステムでは、ポートが2つのグループに分かれます。1~1023は特権を持つポートであり、1024以降は特権を持たないポートです。特権ポートへのバインドには、それを実行できる特権が必要です。一般ユーザーはこの特権を持っていませんが、rootは持っています。そして、このために、rootとして動作するプロセスが1つ必要になるのです。rootとして動作するApacheプロセスの権限リストを思い出してください。このプロセスはすべての特権を持っていますが、必要な特権はそれらのうちの1つだけです。ただし、その特権は、基本特権セットに含まれていません。
予想される所要時間:10分間
特権を認識するプロセスと特権を認識しないプロセスの両方についてすでに学習しました。ここでは、SMFを使用して、制限された特権セットを持つユーザーに特権を認識しないプロセスを管理させる方法と、rootに対するsetuidを使用せずにそのユーザーに必要な特権を与える方法を学習します。
特権を監視または管理するには、プロセス自体がすでにそれらの特権を持っている必要があります。このため、以降の演習のためにrootロールを取得します。
Apacheプロセスには、こうあるべきというものはありません。Solarisでは、任意のユーザーまたはプロセスに特権ポートを使用する特権を与えることができます。rootプロセスはもはや不要です。
そこで、この方法でApacheプロセスを構成してみます。まず、演習3から動作しているApacheを非アクティブ化する必要があります。
oracle@solaris:~$ su - root Password: <root password> oracle@solaris:~# svcadm -v disable -s apache22 svc:/network/http:apache22 disabled.
ここでは、サービス管理機能(SMF)について説明しませんが、SMFで特定のプロパティを設定することにより、サービスの起動を制御できます。
1 oracle@solaris:~# svccfg -s apache22 2 svc:/network/http:apache22> setprop start/user = astring: webservd 3 svc:/network/http:apache22> setprop start/group = astring: webservd 4 svc:/network/http:apache22> setprop start/privileges = astring: 5 basic,!proc_session,!proc_info,!file_link_any,net_privaddr 6 svc:/network/http:apache22> setprop start/limit_privileges = astring: :default 7 svc:/network/http:apache22> setprop start/use_profile = boolean: false 8 svc:/network/http:apache22> setprop start/supp_groups = astring: :default 9 svc:/network/http:apache22> setprop start/working_directory = astring: :default 10 svc:/network/http:apache22> setprop start/project = astring: :default 11 svc:/network/http:apache22> setprop start/resource_pool = astring: :default 12 svc:/network/http:apache22> end
もっとも興味深いのは、2~4行目です。何も変更していない状態で、Apacheデーモンはrootとして起動し、常にwebservdユーザーによってプロセスを分岐します。しかし、この構成のrootユーザーを排除する必要があります。そこで、webservdユーザーによってデーモンを直接起動し、同じことをグループIDについても実行します。
ここで、さらに興味深いことがあります。この行(4行目)がないと、カーネルは、Apacheのポート80へのバインドを拒否します。webservdは、特権ポートを使用する特権を持たない一般ユーザーです。start/privilegesプロパティにより、これらの特権がサービスを起動するように設定されます。まず、サービスに基本特権を与えます。次に、特権ポートを使用する特権を追加します。これで、サービスを起動します。
ただし、まだできることがあります。Webサーバーは、ハードリンクを実行するべきではありません。また、Webサーバーは、そのセッションの外部にシグナルを送信しません。さらに、Webサーバーは、シグナルを送信できるプロセス以外のプロセスのステータスを調べません。このため、これらの特権は不要です。proc_session、proc_info、およびfile_link_anyは、基本特権セットに含まれています。特権の前に!を追加することにより、これらの特権を削除します。
oracle@solaris:~# svcadm -v refresh apache22 Password: Action refresh set for svc:/network/http:apache22.
これで、SMFに構成の変更が通知されました。
これまで、Apacheデーモンは、root特権を使用していました。このため、ファイルおよびディレクトリの所有権に関しては、複雑ではありませんでした。デーモンは、システム内の任意のディレクトリまたはファイルの読取り/書込みを実行できました。一般ユーザーを使用してデーモンの特権セットを削除するため、一部のファイルの所有権を変更したり、一部のファイルを削除したりする必要があります。
oracle@solaris:~# mkdir -p -m 755 /var/apache2/2.2/run oracle@solaris:~# chown webservd:webservd /var/apache2/2.2/run oracle@solaris:~# chown webservd:webservd /var/apache2/2.2/logs/access_log oracle@solaris:~# chown webservd:webservd /var/apache2/2.2/logs/error_log
| 注: サービスはrootとして動作しなくなりますが、トレードオフが発生します。"root"構成では、ログは、rootによって所有されており、"webservd"による変更は不可能でした。新しいモデルでは、Webサーバーの特権が減っていますが、ログは、"webservd"によって所有され、書込み可能になっています。これは、良くも悪くもなく、単なるトレードオフです。 |
また、構成の一部を変更する必要もあります。LockFileとPidFileを移動しなければなりません。前に指定した2つの構成ディレクティブのうちの1つがなかったため、単にこれらを構成ファイルの最後に追加します。
oracle@solaris:~# bash -c 'echo LockFile /var/apache2/2.2/logs/accept.lock >> /etc/apache2/2.2/httpd.conf' oracle@solaris:~# bash -c 'echo PidFile /var/apache2/2.2/run/httpd.pid >> /etc/apache2/2.2/httpd.conf'
これで、すべての準備が整いました。では、試してみましょう。
oracle@solaris:~# svcadm -v enable -s apache22 svc:/network/http:apache22 enabled.
ここで、動作しているhttpdプロセスを調べます。
oracle@solaris:~# ps -ef | grep "httpd" | grep -v "grep" webservd 2064 2057 0 08:43:24 ? 0:00 /usr/apache2/2.2/bin/httpd -k start webservd 2061 2057 0 08:43:24 ? 0:00 /usr/apache2/2.2/bin/httpd -k start webservd 2062 2057 0 08:43:24 ? 0:00 /usr/apache2/2.2/bin/httpd -k start webservd 2060 2057 0 08:43:24 ? 0:00 /usr/apache2/2.2/bin/httpd -k start webservd 2063 2057 0 08:43:24 ? 0:00 /usr/apache2/2.2/bin/httpd -k start webservd 2057 1 1 08:43:23 ? 0:00 /usr/apache2/2.2/bin/httpd -k start
違いが分かりますか。rootとして動作しているhttpdが存在しません。すべてのプロセスが、webservdのユーザーIDで動作しています。これで、目的は達成されました。
プロセスの特権を調べましょう。最初に、以前はrootとして動作していたものを調べます。
oracle@solaris:~# ppriv 2057
2057: /usr/apache2/2.2/bin/httpd -k start
flags = <none>
E: basic,!file_link_any,net_privaddr,!proc_info,!proc_session
I: basic,!file_link_any,net_privaddr,!proc_info,!proc_session
P: basic,!file_link_any,net_privaddr,!proc_info,!proc_session
L: all
root特権ではなく、ジョブを実行するための最小特権のみが与えられています。さらに、他のプロセスに関するセキュリティも向上しています。Webサーバーの構成を変更する前は、Webサーバーが一般ユーザーの基本特権を持っていました。現在では、この特権セットも制限されています。
ただし、やはり、Apacheを起動するには、特権を持つユーザーである必要があります。特権を持たないユーザーに"サービス"の管理を委任できれば、状況がさらに改善されます。認証を使用することで、これを実現できます。また、認証は、SMFと統合されます。ユーザーにapach22サービスを管理する権限を与えるために、2つの認証をユーザーに追加する必要があります。サービスを管理するための認証と、サービスの状態を変更するための認証が必要です。
サービスの状態はサービスのプロパティとして保持されるため、サービスの状態の変更には両方の認証が必要です。
oracle@solaris:~# svcprop http:apache22 | grep auth httpd/value_authorization astring solaris.smf.value.http/apache22 general/action_authorization astring solaris.smf.manage.http/apache22 general/value_authorization astring solaris.smf.value.http/apache22
最初に、認証を/etc/security/auth_attrに追加する必要があります。
oracle@solaris:~# echo solaris.smf.manage.http:::Mange Apache 2.2:: >> /etc/security/auth_attr Password: oracle oracle@solaris:~# echo solaris.smf.value.http:::Mange Apache 2.2:: >> /etc/security/auth_attr
| 注: ほとんどのSMFマニフェストでは、action_authorizationとvalue_authorizationの両方に1つの認証が使用されます。これは、それらが一般に、一緒に使用されるためです。 |
特権の操作が完了したため、ここで、rootロールを終了できます。前から使用しているjdoeユーザーに認証を追加しましょう。
oracle@solaris:~# exit oracle@solaris:~$ usermod -A solaris.smf.manage.http/apache22,solaris.smf.value.http/apache22 jdoe oracle@solaris:~$ userattr auths jdoe solaris.smf.manage.http/apache22,solaris.smf.value.http/apache22
jdoeがApacheを起動および停止できることを確認しましょう。
oracle@solaris:~$ su - jdoe Password: abc123 Oracle Corporation SunOS 5.11 11.0 November 2011 jdoe@solaris:/export/home/jdoe$ /usr/sbin/svcadm enable apache22 jdoe@solaris:/export/home/jdoe$ svcs apache22 STATE STIME FMRI online 8:43:23 svc:/network/http:apache22 jdoe@solaris:/export/home/jdoe$ /usr/sbin/svcadm disable apache22 jdoe@solaris:/export/home/jdoe$ svcs apache22 STATE STIME FMRI disabled 8:53:37 svc:/network/http:apache22
正常に機能したこと、つまり、SMFを使用して、Apacheなどのサービスを操作できるようになり、必要最小限の特権がサービスに与えられてrootとして起動する必要がなくなっていることを確認します。また、Apacheには不要でありながら、ハッカーがシステムを制御するために必要とする、一部の特権も削除されました。
さらに、ここで表示されるように、特権を持たないユーザーに、特定のサービスのみの管理を許可する適切な認証を与えることにより、SMFによってApacheサービスを管理する権限をそれらのユーザーに追加しました。
jdoe@solaris:/export/home/jdoe$ svcs sendmail STATE STIME FMRI online 6:48:12 svc:/network/smtp:sendmail jdoe@solaris:/export/home/jdoe$ svcadm disable sendmail svcadm: svc:/network/smtp:sendmail: Permission denied.
これで、Oracle Solarisのセキュリティ機能によるアプリケーションの保護に関するハンズオン・ラボは無事に完了です。
このラボで使用したテクノロジーについて詳しくは、次のリンクにアクセスしてください。
http://www.oracle.com/technetwork/server-storage/solaris/overview/security-163473.html
http://www.oracle.com/us/products/servers-storage/solaris/security/index.html
Restricting Service Administration in the Solaris 10 OS
Limiting Service Privileges in the Solaris 10 OS
Privilege Debugging in the Solaris 10 Operating System
Privilege Bracketing in the Solaris 10 Operating System
ご参加くださり、ありがとうございました。
false