Windowsのユーザー境界の知識マップ(知識グラフ)
ユーザープロファイルは実行ユーザーのSIDを前提に作られ、%LOCALAPPDATA%・%APPDATA%(Roaming)・NTUSER.DATはそのプロファイル配下に保存され、CurrentUserスコープのDPAPIマスターキーもプロファイル配下に置かれる。ユーザーの証明書ストアの実体はHKCU配下のレジストリにある。通常のログオンではHKCU(Classes配下を除く)の実体はロードされたNTUSER.DATであり(LocalSystemでは既定ユーザーに関連付く)、サービスからHKCUを使うことは推奨されない。DPAPIはマスターキーで秘密を保護するため、CurrentUserスコープは別ユーザーからの復号失敗の原因になることがあり、LocalMachineスコープはそれを軽減する。資格情報マネージャーの中身はDPAPIで保護され、保存したユーザーの文脈でのみ使える。Chromium系ブラウザーのプロファイルは既定で%LOCALAPPDATA%配下にありDPAPIを利用するので、フォルダーコピーではログイン状態を持ち出せない。タスクスケジューラの実行はログオン種別で、IISアプリケーションプールのプロファイル読み込みはloadUserProfile設定で構成する。S4Uログオンは暗号化ファイル(EFS)とも資格情報マネージャーの金庫とも両立せず、管理者によるパスワードリセットはDPAPI復号失敗の原因になり得る。ASP.NET Core Data Protectionの鍵リングはプロファイルが使える環境で%LOCALAPPDATA%に置かれDPAPIで暗号化される。全ユーザー・サービスで共有するデータにはProgramData配下、サービスの証明書にはコンピューターの証明書ストアが推奨される。ネットワークドライブの割り当てはログオンセッションに保存され、UAC昇格したプロセスからは既定で見えない。実行ユーザーのSIDはwhoamiとProcess Explorerで、実際に読まれたプロファイル配下のパスはProcess Monitorで確認できる。AppData\LocalLowもプロファイル配下にあり、HKCU\Software\Classesの実体UsrClass.datは%LOCALAPPDATA%配下に置かれる。サービスがユーザーの設定を読む必要がある場合は偽装(impersonation)とRegOpenCurrentUserの利用が推奨される。LocalServiceアカウントは自分のユーザープロファイルを持ち、LocalSystemのコンテキストはPsExecで対話シェルを開いて確認できる。
管理者によるパスワードのリセット
ネットワークドライブ(マップされたドライブ文字)
SID(セキュリティ識別子)
Windowsがユーザーやグループなどのセキュリティプリンシパルを一意に識別するために使う識別子。アクセストークンに含まれ、ACL判定やプロファイルの紐づけの基準になる。
ユーザープロファイル
ファイルシステム上のプロファイルフォルダー群と、ユーザーレジストリハイブNTUSER.DATから成る、サインインしたユーザーの作業環境の実体。
Windowsユーザープロファイル
DPAPI
実行中のマシン上でアプリの秘密情報を保護するWindowsのデータ保護API。
データ保護API
資格情報マネージャー(cmdkey)
サーバーごとの資格情報をユーザープロファイル単位で保存し、以後の認証時に自動的に提示する仕組み。サービスで使うにはその実行アカウントのコンテキストで登録する必要がある。
NTUSER.DAT
Windowsのユーザープロファイルに含まれるユーザーレジストリハイブの実体ファイルで、サインイン時に読み込まれてHKEY_CURRENT_USERとして使われる。
ユーザーレジストリハイブ
HKCUの実体
HKEY_CURRENT_USER(HKCU)
セッションではなくログオンユーザーに紐付くレジストリのルートキーで、同一ユーザーの複数セッション間で値が共有される。
Windowsサービス
ユーザーのサインインと無関係にバックグラウンドで動くWindowsのプロセス。
サービス
%LOCALAPPDATA%
ユーザーごとの、ローミングしないデータを保存する既知フォルダーで、ユーザーごとのデータの既定の置き場所。
%APPDATA%(Roaming)
移動ユーザープロファイル環境でログオン・ログオフ時に同期される既知フォルダー。
DPAPIマスターキー
DPAPIがデータ保護に使うランダム生成の鍵。CurrentUserスコープではユーザーのログオン資格情報から派生した鍵で暗号化(保護)され、ユーザープロファイル配下に保存される。
DataProtectionScope.CurrentUser
DPAPIで保護したデータの復号主体をそのWindowsユーザーに限定するスコープ指定で、通常のデスクトップアプリで基本となる。
CurrentUserスコープ
ユーザースコープ
DPAPI復号失敗
保護時と復号時で紐づくWindowsユーザーやコンピューターの鍵材料が一致せず、ProtectedData.Unprotectが失敗する事象。
復号できないデータ
DataProtectionScope.LocalMachine
DPAPIで保護したデータを同じマシン上で動く任意のプロセスから復号可能にするスコープ指定で、共用端末では危険になりやすい。
LocalMachineスコープ
マシンスコープ
ユーザーの証明書ストア
ユーザーアカウントごとに別に存在する証明書ストア。
現在のユーザーの証明書ストア
Chromium系ブラウザーのプロファイル
履歴・Cookie・拡張機能・保存パスワードなどブラウザーのユーザー状態を保持する、ChromeやEdgeなどChromium系ブラウザーのフォルダー。Windowsでは既定で%LOCALAPPDATA%配下に置かれる(--user-data-dir等で変更可能)。
ブラウザプロファイル(Chrome/Edge)
タスクスケジューラの無人実行
指定したアカウントで、スケジュールやログオンなどのトリガーに従いプログラムを実行するWindowsの仕組み。ログオン種別(対話トークン・パスワード保存・S4Uなど)の設定によっては、ユーザーがログオンしていなくても実行できる。
ログオン種別(LogonType)
タスクの実行アカウントをどう認証するかを決める内部区分。対話トークン(InteractiveToken)・パスワードを保存するPassword・パスワードを保存しないS4Uのいずれかを取り、S4Uはネットワーク上のリソースと暗号化ファイル(EFS)へのアクセスができない。
IISアプリケーションプール
IIS上のWebアプリの実行単位。プールのIDというアカウントで無人実行される。
アプリプールID
loadUserProfile設定
IISアプリケーションプールのワーカープロセスがユーザープロファイルを読み込むかどうかを制御するprocessModelの属性。
S4Uログオン
パスワードを保存せずにユーザーとしてタスクを実行するログオン方式。タスクスケジューラの「パスワードを保存しない」構成で使われ、ネットワークにも暗号化ファイル(EFS)にもアクセスできない。
NTFS暗号化(EFS)ファイル
EFS(Encrypting File System)で暗号化されたファイル。NTFS圧縮と同様、アクセスが同期処理に変換されるため非同期発行でも同期的に完了する。
管理者がユーザーのWindowsパスワードをリセットする操作。DPAPIの保護に使われる鍵材料への紐付けが外れ、保護済みデータへアクセスできなくなることがある。
パスワードリセット
ASP.NET Core Data Protection
Cookie認証などの保護に使うASP.NET Coreのデータ保護基盤。実行環境に応じて鍵リングの保存先を自動選択し、Windowsでユーザープロファイルが使える場合はDPAPIで暗号化する。
%ProgramData%配下の保存先
管理者が1台につき1つ設定し、全ユーザーで共有するマシン単位の設定を置くフォルダー。
コンピューターの証明書ストア
PCに1つで、全ユーザーとサービスに共通の証明書ストア。
ローカルコンピューターの証明書ストア
UNCパスの共有フォルダーに割り当てたドライブ文字(Z:など)で、実体はログオンセッション固有のシンボリックリンクオブジェクト(DosDevices)である。
ドライブ文字
リダイレクトされたドライブ
ログオンセッション
ユーザーのログオンやサービスの起動のたびにOSが作る実行の文脈で、ドライブ文字のマップはログオンSIDに基づきこの単位で管理される。
UAC昇格(管理者として実行)
UAC有効な管理者ユーザーのログオン時に、権限を制限した通常トークンと完全な管理者トークンという、リンクされた2つのログオンセッションが作られる仕組み。
リンクされたログオンセッション
whoamiコマンド
現在のプロセスの実行ユーザー名・SID・グループ・特権を表示するWindowsのコマンド。/userでユーザー名とSID、/allで全情報を表示する。
Process Explorer
プロセスに読み込まれているDLLだけでなく、ハンドル・スレッドスタック・GDI/USERオブジェクト数なども確認できるSysinternalsのプロセス監視ツール。管理者として実行すると他ユーザーやサービスのプロセスも参照できる。
Process Monitor(procmon.exe)
ファイルI/O・レジストリ・プロセス/スレッド活動をリアルタイムに監視できるSysinternalsのツール。Advanced Outputを有効にすると、IRPやファストI/Oのカーネル側の語彙で操作を表示する。
AppData\LocalLow
低整合性レベルで動作するプロセスが書き込める数少ない場所として用意された、プロファイル内のフォルダー。
HKEY_CURRENT_USER\Software\Classes
COMがコンピューター全体の情報を見る前に先に参照する、そのユーザーだけに見えるCOMクラス登録の場所。
偽装(impersonation)
サービスが、接続してきたクライアントユーザーの権限を借りてリモート資源にアクセスする仕組み。
クライアント偽装
LocalServiceアカウント
サービスの実行アカウントの1つ。ネットワーク上では匿名資格情報として認証されるため、共有フォルダーへのアクセスには使えない。
LocalSystemアカウント
サービスの実行アカウントの1つ。ローカルでは広範な特権を持つ一方、ネットワーク上ではコンピューターの資格情報としてリモートサーバーに認証される。
PsExec
リモートまたはローカルで任意のアカウント(SYSTEMを含む)としてプロセスを起動できるSysinternalsのツール。psexec -s -i cmdでSYSTEMのコンテキストの対話シェルを開ける。
ユーザープロファイルは実行ユーザーのSIDに紐づいて作られ(ProfileListはSIDをキーに持つ)、SIDが異なれば初期状態から始まる別のプロファイルになる。
ユーザーレジストリハイブの実体NTUSER.DATはユーザープロファイルに含まれ、ログオン時にロードされる。
対話ログオンしたユーザーのプロセスでは、HKEY_CURRENT_USERの中身(HKCU\Software\Classes配下を除く)はログオン時にロードされたそのユーザーのNTUSER.DATがマップされたものになる。Classes配下は別ファイルUsrClass.datが実体で、LocalSystemのように既定ユーザーへ関連付くコンテキストでもこの関係は成り立たない。
サービスからHKEY_CURRENT_USERへアクセスすべきではない。LocalSystemのプロセスではHKCUが既定ユーザーに関連付けられ、ユーザーの設定が必要な場合はそのユーザーを偽装したうえでRegOpenCurrentUserを使う。
%LOCALAPPDATA%はユーザーごとの既知フォルダーで、実行ユーザーのプロファイル配下に解決される。
%APPDATA%(Roaming)はユーザーごとの既知フォルダーで、既定では実行ユーザーのプロファイル配下に解決される。移動プロファイルやフォルダーリダイレクトを構成したドメイン環境では別の場所になり得る。
DPAPIはOSが管理するマスターキーで暗号化・復号を行い、アプリケーション側は鍵を保持・管理しない。
CurrentUserスコープで使われる、ランダムに生成されたユーザーのマスターキーは、ログオン資格情報から派生した鍵で暗号化されてユーザープロファイル配下に保存される。LocalMachineスコープのマシン共通の鍵はこの対象外。
CurrentUserスコープで保護したデータを、暗号化したユーザーと異なる実行ユーザー(サービス化・タスク化後のアカウントなど)から復号しようとすると失敗する。
サービスと対話ユーザーの両方から読む秘密をLocalMachineスコープで保護すれば、実行ユーザーの違いによる復号失敗を避けられる。同じマシンの任意のプロセスが復号できるため、読者はファイルACLで絞る。
資格情報マネージャーに保存された資格情報はディスク上に置かれDPAPIで保護されるため、復号して使えるのは保存したユーザーの文脈に限られる。
ユーザーの証明書ストアの実体はレジストリのHKEY_CURRENT_USER\Software\Microsoft\SystemCertificates配下にあり、ユーザーごとに分かれる。
ChromeのUser Dataディレクトリは既定で%LOCALAPPDATA%配下にあり、履歴・Cookie・保存パスワードなどのプロファイルはそこに置かれる。--user-data-dirや自動化ツールの永続ディレクトリ指定で別の場所を使う場合はこの限りではない。
ChromeはWindowsでCookie等の暗号鍵の保護にDPAPIを使っており(現在はアプリ束縛暗号化を併用)、プロファイルを別ユーザー・別マシンへコピーしても鍵を復号できない。
タスクの実行はInteractiveToken・Password・S4Uのログオン種別で構成し、S4Uではパスワードが保存されずネットワークにも暗号化ファイルにもアクセスできない。
アプリケーションプールのワーカープロセスがユーザープロファイルを読み込むかはprocessModelのloadUserProfile属性で構成する。IISは既定ではプロファイルを読み込まない。
S4Uログオンではパスワードが保存されないため、暗号化ファイル(EFS)にもネットワークリソースにもアクセスできない。
S4Uログオンはネットワーク資格情報を持たないため、実行アカウントの金庫に資格情報を投入しても使えない。使うにはパスワードを保存する構成などへの切り替えが必要になる。
ローカルアカウントのパスワードを管理者がリセットすると、マスターキーを守る鍵の材料が失われ、過去にCurrentUserスコープで保護した暗号文が復号できなくなることがある(ユーザー自身のパスワード変更操作では復号能力を引き継ぐ)。
ユーザープロファイルが使える環境では、Data Protectionの鍵リングはDPAPIで暗号化される。IISホストでプロファイルが無い場合はワーカープロセスアカウントにACLされたHKLMレジストリへフォールバックする。
ユーザープロファイルが使える環境では、鍵リングは%LOCALAPPDATA%のASP.NET/DataProtection-Keysに保存される。どの条件にも当てはまらない環境では一時キーになり、再起動で保護済みデータが無効になる。
マシン上の全ユーザー・サービスで共有するデータは、実行ユーザーのプロファイルに解決されるAppDataではなくProgramData配下に置き、ACLを設計するのが本記事の推奨。
サービスから使う証明書はコンピューターの証明書ストアに入れ、秘密鍵のACLでサービスアカウントに読み取りを許可するのが本記事の推奨。CurrentUserストアの秘密鍵にはサービスの実行ユーザーから届かない。
ネットワークドライブの割り当てはログオンセッション単位で保持される。UAC有効な管理者は標準トークンと昇格トークンで別のログオンセッションを持つため、片方で割り当てたドライブ文字はもう片方から見えない。
標準トークンのセッションで割り当てたドライブ文字は、昇格したプロセスのログオンセッションからは既定で参照できない。
実行ユーザーのユーザー名とSIDはwhoami /userで、グループ・特権まで含めた全体はwhoami /allで確認できる。ユーザー境界トラブルの調査はここから始める。
プロセスのトークンがどのユーザー・どのセッションのものかは、Process Explorerで確認できる。
アプリが実際にどのプロファイル配下のパス・レジストリキーを読んだかはProcess Monitorで確認できる。PATH NOT FOUNDの行に現れる期待と違うプロファイルのパスが、ユーザー境界を踏んでいる手がかりになる。
AppData\LocalLowもユーザープロファイル配下の既知フォルダーで、低い完全性レベルで動くプロセス用の書き込み先として区分されている。
HKCU\Software\Classesはユーザーごとの別ハイブで、実体ファイルUsrClass.datは%LOCALAPPDATA%のMicrosoft/Windows配下に置かれる。NTUSER.DATとは別に管理される。
サービスがユーザーの設定を読む必要がある場合は、HKCUを直接開くのではなく、そのユーザーを偽装したうえでRegOpenCurrentUserを使うのが推奨される。
LocalServiceアカウントはC:\Windows\ServiceProfiles配下に自分のプロファイルを持ち、HKEY_USERSに自分のサブキーを持つ(NetworkServiceも同様)。対話ユーザーのプロファイルとは別物になる。
psexec -s -i cmdでSYSTEM(LocalSystem)のコンテキストの対話シェルを開き、SYSTEM側の世界から同じ操作を再現してユーザー境界の問題を確認できる。