サービスを最小特権で実行する

今回は Windows サービスを作成する上でのセキュリティ上のポイントを軽く紹介する.
Windows Vista では,サービスをより安全に実行するために Service Control Manager (SCM) の改善が行われている.ポイントとなるのは,必要特権リストの指定が可能になったこと,および制限された SID を割り当てられるようになったことだ.
たとえば,特定ファイルを物理メモリ上に保持し続けるサービスを作りたいとする.この処理をサービスにする必要があるのは,それが特権を必要とするからだ.VirtualLock API でロック可能なメモリ領域は通常 30 ページに制限されており,SetProcessWorkingSetSize API でその制限を拡大するには,SE_INC_BASE_PRIORITY_NAME 特権が必要である.しかし,単純に System アカウントで動くサービスを作ったのでは,余分な特権まで有効にされてしまう.これは最小特権の原則に反する.
ここで,以下のように ChangeServiceConfig2 API を利用することで,サービスに付与される特権を制限できる.

SERVICE_REQUIRED_PRIVILEGES_INFO privileges_info = {};
privileges_info.pmszRequiredPrivileges = SE_INC_BASE_PRIORITY_NAME _T("\0");
ChangeServiceConfig2(service_handle, SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO,
                     &privileges_info);

また,このサービスはファイルやレジストリに書き込む必要がない.そこで,以下のように設定することで,意図せずファイルやレジストリに書き込もうとしたときに失敗するように構成できる.

SERVICE_SID_INFO sid_info = {};
sid_info.dwServiceSidType = SERVICE_SID_TYPE_RESTRICTED;
ChangeServiceConfig2(service_handle, SERVICE_CONFIG_SERVICE_SID_INFO,
                     &sid_info);

このように設定したサービスを起動し,Process Explorer でセキュリティ情報を見てみる.
f:id:NyaRuRu:20121015010639p:plain
Restricted SID が設定されていること,"NT AUTHORITY\WRITE RESTRICTED" SID が設定されていること,特権が大幅に削除されていることなどがわかる.
実際,OS 標準のサービスは概ね最小特権で実行されている一方で,(残念ながら Microsoft Office を含む) OS 非標準のサービスは,デフォルトの特権を持ったまま動作しているものがほとんどだ.例えば,Office 2010 に付属する ImeDictUpdateService (Microsoft IME Dictionary Update) のセキュリティ属性は以下のようになる.
f:id:NyaRuRu:20121015010658p:plain
デフォルトで付与される全ての特権を持ったまま実行されていることが分かる.これが本当に IME の辞書アップデートサービスであるなら,SeDebugPrivilege (スーパー特権のひとつ.プロセスのセキュリティ設定を無視して,(保護されたプロセスをのぞく) すべてのプロセスを開くことができる.) や,SeTimeZonePrivilege (文字通りタイムゾーンを設定するための特権) をはじめとした,多くの特権を削除しても恐らく動作は可能だろう.