管理者権限処理の分離実装【Windowsアプリ】
結論
Windowsアプリで管理者権限が必要な処理がある場合、アプリ全体を管理者として動かすのではなく、管理者権限が必要な部分だけを別EXEに分離するのが安全かつ実務的です。
- UIアプリは
asInvokerのまま動かす - 管理者処理は別EXE(helper)に切り出し、
requireAdministratorにする - helperの起動は
runasを使う - helperとの通信は名前付きパイプなどのIPCを使う
- helperに渡すのは型付きの要求だけにする
- helper側で要求内容を再検証する
前提:同じプロセスの一部だけを管理者化できない
WindowsのUACはプロセス単位です。同じプロセスの中で「この処理だけ管理者権限」はできません。管理者処理が必要なら、別プロセスやサービスなど別の実行単位に切り出します。
分離モデルの選び方
| モデル | 説明 | 向いている場面 |
|---|---|---|
| Administrator Broker | UI(asInvoker) + 管理者helper EXE | 必要な瞬間だけUACを出せばよい場合 |
| OS Service | UI + 常駐サービス | 常時稼働の管理機能 |
| Elevated Task | UI + 管理者権限タスク | 1回ごとの定型処理 |
| COM Object | UI + 昇格COM | 既存COM設計がある限定的な場合 |
最初に検討しやすいのは broker EXE です。設定画面の特定ボタンを押した時だけ管理者権限が必要になるようなケースに最適です。
おすすめ構成
[MyApp.exe] asInvoker
|
| runas
v
[MyApp.AdminBroker.exe] requireAdministrator
|
| named pipe
v
[管理者操作を実行]
ポイント:
- UIプロセスは最後まで非昇格
- 管理者helperは短命
- helperが受け付ける操作は固定の許可リストのみ
実装で守るべきルール
helperは「なんでも屋」にしない
ダメな例:UIからhelperに生のコマンド文字列(reg add ... など)を渡す。これだとUIが侵害されたらhelperも一緒に壊れます。
良い例:操作名を固定する(set-explorer-context-menu、install-service など)。引数も bool、enum、数値、限定された文字列に絞ります。
起動経路の注意点
- helper EXEのパスは絶対パスで指定する
- .NETでは
UseShellExecute=trueを明示する(Verb="runas"はUseShellExecute=trueでのみ有効) runasと標準入出力リダイレクトは相性が悪いので、IPCは名前付きパイプを使う
名前付きパイプのセキュリティ
- 既定のACLに頼らず、明示的な
PipeSecurityを設定する PipeOptions.CurrentUserOnlyは非昇格UIと昇格helperの通信には使えない(昇格レベルも確認するため)- UI側で自分のSIDを取得してhelperに渡す
- helper側ではUIユーザーSIDだけにpipe接続権を与える
GetNamedPipeClientProcessIdで接続元PIDも確認する
PID検証について
PID検証は「同じユーザーの別プロセスが先に接続する」のを防ぐ追加防御です。ただしPIDが一致していてもUIが侵害されていれば危険な要求が届くため、operation許可リストと引数検証が本質的な防御です。
具体的なコード例
共通契約(BrokerProtocol)
操作名とリクエスト/レスポンス型を別プロジェクトで定義します。
public static class BrokerOperations
{
public const string SetExplorerContextMenu = "set-explorer-context-menu";
}
public sealed record BrokerRequest(string Operation, JsonElement Payload);
public sealed record BrokerResponse(bool Success, string? ErrorCode, string? Message);
pipeにはJSONを長さ付きで送ります(ヘッダ4バイト+ペイロード)。
UI側(ElevationBrokerClient)
- helper EXEの起動は
ProcessStartInfoでUseShellExecute=true, Verb="runas"を指定 - ランダムなpipe名を生成し、自分のPIDとSIDをhelperに渡す
- pipe接続後に型付きリクエストを送信
helper側(AdminBroker)
- 起動引数からpipe名、client PID、client SIDを受理
- pipeのACLを明示的に組み立てる(呼び出し元UIユーザーSIDに接続権を付与)
- 接続後にclient PIDを検証
switch (request.Operation)で固定操作のみdispatch
管理者操作の実装例
たとえばExplorerの右クリックメニューをレジストリに登録する処理では:
- UIから任意のレジストリパスを受け取らない
- UIから任意のコマンド文字列を受け取らない
- 登録対象EXEはhelper側で固定解決
- リクエストの内容は
Enabled(bool)だけ
これでhelperは「Explorer右クリックメニューの登録状態を切り替える」という1つの意味しか持ちません。
よくあるNGパターン
- UI全体を
requireAdministratorにする — 権限境界を雑に潰す - helperに生の文字列コマンドを渡す — helperが汎用実行口になる
- 名前付きパイプの既定ACLをそのまま使う — 明示的にACLを設定すべき
CurrentUserOnlyに飛びつく — 非昇格UI↔昇格helperには向かない- helperが任意パスを受け取って操作する — 操作は必ず固定化する
まとめ
- UIは
asInvoker、helperはrequireAdministrator - 通信は名前付きパイプ、pipe ACLとclient PIDで接続元を絞る
- helperは固定operationしか受けず、引数を再検証する
- この設計は後からservice化する際にも移行しやすい
参考資料
- 元記事: Windowsアプリ開発における最低限のセキュリティを守るためのチェックリスト
https://comcomponent.com/blog/2026/03/14/001-windows-app-security-minimum-checklist/ - Administrator Broker Model - Win32 apps
- Developing Applications that Require Administrator Privilege
- Operating System Service Model - Win32 apps
- Elevated Task Model - Win32 apps
- Administrator COM Object Model - Win32 apps
- The COM Elevation Moniker
- How User Account Control works
- ProcessStartInfo.UseShellExecute
- Named Pipe Security and Access Rights
- PipeOptions Enum
- NamedPipeServerStreamAcl.Create
- GetNamedPipeClientProcessId
- RegistryView Enum
関連する記事
同じタグを共有する最新の記事です。さらに近い話題で知識を深められます。
設定ファイルの機密情報を安全に保存する方法
Windowsデスクトップアプリでパスワードやトークンを設定ファイルに平文で置くリスクと、DPAPI(ProtectedData)を使った保護のしどころ、CurrentUserとLocalMachineの選び方、optionalEntropyやログ運用の注意点までC#実装例...
Windowsアプリのセキュリティチェックリスト
WPF・WinForms・WinUI・C++・C# など Windows アプリ開発で最低限外したくないセキュリティ項目を、権限・署名・秘密情報・通信・入力・DLL・ログの観点でチェックリスト化し、リリース前に何を確認すべきか整理した記事です。
Windows管理者特権の必要/不要の境界
Windowsで管理者特権が必要になる場面を、UAC、保護領域、サービス、ドライバ、per-user/per-machine 配布の観点で整理し、無駄な昇格を減らす設計の見分け方と典型例、よくある誤解までを実務向けにまとめます。
Windowsはなぜ今の形になったのか:開発者から見た歴代Windowsの進化
Windows 95からWindows 11までの変化を、見た目の年表ではなく、互換性、安定性、権限管理、ドライバ、Win32、.NET、セキュリティなどWindowsアプリ開発者の視点で整理します。
Windowsで「Windows によって PC が保護されました」が出る理由
Windowsアプリ配布時にSmartScreen警告が出る理由を、コード署名、EV/OV証明書、Azure Artifact Signing、MSIX、Microsoft Store、ClickOnce、社内配布、App Controlまで実務目線で整理します。
関連トピック
このテーマと近いトピックページです。記事を起点に、関連するサービスや他の記事へ進めます。
Windows技術トピック
Windows 開発、不具合調査、既存資産活用の技術トピックをまとめた入口です。
このテーマがつながるサービス
この記事は次のサービスページにつながります。近い入口からご覧ください。
Windowsアプリ開発
業務アプリ、装置連携、通信ツールなどの Windows ソフト開発を支援します。