セッション0
Windows Vista以降、サービスなど対話的ユーザーに関わらないプロセス専用に予約された、ユーザーの対話的セッションとは分離されたセッション。
Remote Desktop Services(RDS)
1台のWindows Serverに複数ユーザーが同時にログオンし、それぞれ独立したセッションでデスクトップやアプリを使えるようにするサーバーの役割・機能群。
リモートデスクトップサービス
名前付きカーネルオブジェクトのセッション名前空間
Mutex・イベント・セマフォなどの名前付きカーネルオブジェクトが、プレフィックスを付けない限りセッションごとに独立して配置される名前空間。
Local名前空間
Windowsサービス
ユーザーのサインインと無関係にバックグラウンドで動くWindowsのプロセス。
サービス
ウィンドウメッセージ経由の権限昇格
標準権限のプロセスが同じセッション内のSYSTEM権限プロセスのウィンドウへ細工したメッセージを送り込み、処理を乗っ取って権限を昇格させる攻撃手法。
プロセス間通信(IPC)
別プロセスとデータや合図をやり取りする仕組みの総称。
名前付きパイプ
Windowsのプロセス間通信手段のひとつ。リモートからの利用はアプリ自身のポートではなくSMB(TCP 445)を経由する。
Elevated Task Model
標準ユーザーのUIアプリから、管理者権限で動くスケジュールタスクを起動して短い定型処理を行わせる権限分離モデルである。
最高権限タスクモデル
タスクスケジューラの無人実行
指定したアカウントで、スケジュールやログオンなどのトリガーに従いプログラムを実行するWindowsの仕組み。ログオン種別(対話トークン・パスワード保存・S4Uなど)の設定によっては、ユーザーがログオンしていなくても実行できる。
管理者権限
コンピューター全体の設定を変更できる権限。
昇格
名前付きMutex
名前を指定して作成し、その名前を知っている他のプロセスからも同じインスタンスを参照できる、相互排他用のWindowsカーネルオブジェクト。
名前付きミューテックス
Global\プレフィックス
名前付きカーネルオブジェクトを、セッション個別のLocal名前空間ではなくマシン全体で共通のGlobal名前空間へ明示的に配置するための名前の接頭辞。
グローバル名前空間
意図しない多重起動
名前付きオブジェクトが既定のセッション名前空間に置かれたままGlobal\を明示しなかった結果、RDS環境などでユーザーごとにアプリが複数起動できてしまう状態。
多重起動防止(シングルインスタンス化)
同一アプリケーションの起動を、セッション・ユーザー・マシンなど選んだ単位で1つに制限する設計。
多重起動対策
RDP(リモートデスクトッププロトコル)
Windowsのリモートデスクトップ接続で、画面表示や入力をネットワーク越しにやり取りするプロトコル。
RDS CAL(クライアントアクセスライセンス)
RD Session Hostロールを介した一般利用に必要な、per deviceまたはper userで発行されるRemote Desktop Servicesのライセンス。
WTSGetActiveConsoleSessionId
物理コンソールに接続されているセッションIDを取得するWin32 APIで、RDP経由のセッションは対象に含まない。
GetSystemMetrics(SM_REMOTESESSION)
呼び出しプロセスがリモートセッションに紐付いているかを判定するWin32 APIの指定値で、RemoteFX vGPU使用時に誤判定する制約がある。
ProcessIdToSessionId
指定したプロセスIDが属するセッションIDを取得するWin32 APIで、クライアント/サーバー型アプリがセッションを識別するために使う。
セッションごとの一時フォルダー
Remote Desktop Servicesが既定で作成する、ユーザープロファイル配下にセッションIDを名前に含む個別の一時フォルダー。
デバイスリダイレクション
RDSセッションからクライアント側のローカルドライブ・プリンター・USBデバイスなどをサーバー側セッションで使えるようにする機構。
HKEY_CURRENT_USER(HKCU)
セッションではなくログオンユーザーに紐付くレジストリのルートキーで、同一ユーザーの複数セッション間で値が共有される。
セッション間の意図しない状態共有
同一ユーザーが複数セッションを持つ環境で、セッションごとに独立させたい状態をHKCUなどユーザー単位の場所に置いたために他セッションへ影響してしまうこと。
Windowsサービスはセッション0という隔離されたセッションで実行され、ユーザーと直接対話できない
サービスとユーザーセッションをセッション0で分離したことで、標準権限のプロセスがサービスのウィンドウへ直接メッセージを送り込む権限昇格の経路が構造的に塞がれた
UIが必要な場合はサービスとUIアプリをプロセス分離し、プロセス間通信で会話する構成にする
サービスとUIアプリ間で通信する場合、その手段の一つとして名前付きパイプなどが案内されている
昇格タスクモデルは、標準ユーザーが起動できるセキュリティ記述子を持つSYSTEMタスクをタスクスケジューラに登録することを前提とする
SYSTEM権限で実行されるタスクの登録には管理者権限が必要で、SYSTEMアカウント自体には対話的なログオン権がない
プレフィックスを付けずに作成した名前付きMutexは、既定でそのセッション専用のLocal名前空間に配置される
マシン全体で1つのMutexに絞りたい場合は、名前の先頭にGlobal\を付けてグローバル名前空間へ明示的に配置する
セッションごとに独立した名前空間があるため、既定の名前のままだと別ユーザーのセッションでは別のMutexとして扱われ、ユーザーごとに1つずつ起動できてしまう
名前付きMutexをGlobal\付きで作成したうえで、自分が先に作成できたか(createdNew)を確かめ、既に別のインスタンスが所有していれば終了する — この判定まで含めて初めて、RDS環境で複数ユーザーが同時ログオンしていてもマシン全体でインスタンスを1つに絞れる。Global\を付けるだけでは名前空間がマシン全体になるだけで、どのプロセスもそのMutexを開けてそのまま動き続けてしまう
RDSはRDP接続を介して複数ユーザーの同時セッションを提供するマルチセッション型の基盤である
2つの管理接続を超える利用にはRD Session Hostロールの導入と適切なRDS CALが必要になる(2つまでの管理用リモート接続はRDS CALなしで利用できる)
WTSGetActiveConsoleSessionIdが返すのは物理コンソールに接続されたセッションだけで、RDP経由でログオンしている複数ユーザーのセッション特定には使うべきでない
自プロセスがリモートセッションに紐付いているかはGetSystemMetrics(SM_REMOTESESSION)で確認できる
同じマシンからの複数セッションを区別したいサーバー側は、ProcessIdToSessionIdでセッションを識別できる
RDSは既定でセッションごとに個別の一時フォルダーを作成し、アプリが%TEMP%を使っていればこの分離の恩恵を受けられる
RDSセッションからクライアント側のローカルデバイスへアクセスするにはリダイレクション機構を経由する
HKCUはセッションではなくログオンユーザーに紐付くため、同一ユーザーが複数セッションを持つ構成ではセッションごとに独立させたい状態をHKCUに置くと他セッションへ意図せず影響する
セッション0で動くサービスがUIを必要とする場合、IPCでの分離に加え、タスクスケジューラの昇格タスクモデルで対話ユーザー側にUIを持たせる方法も選択肢となる
RDSで同一ユーザーアカウントを複数セッションで共有している構成では、セッションごとに独立させたい状態をHKCUなどユーザー単位の場所に置くと他セッションへ意図せず影響する