特権が必要なプログラムを実行する際に、
といったダイアログが出ることがあります。これは、UACが有効である場合に、制限されている特権を使用する許可を求めているものです。ただ、このダイアログはUACで制限されている特権を使用しようとすると表示されるものではありません。
例えば、timeコマンドを考えてみます。timeコマンドはシステムの時刻を変更できるコマンドで、実行にはSeSystemtimePrivilegeが必要です。ですが、この特権はUACによる特権制限の対象なので、Administratorでログインしたとしても与えられません。そして、通常の方法で起動したコマンドプロンプトから実行しようとすると、
> time 10:00:00
A required privilege is not held by the client.
というエラーが出ます。つまり、UACで制限されている特権を使用しようとするだけでは、先ほどのようなダイアログは出ずにエラーになります。
では、どのようにすればダイアログを出せるかというと、ManifestをPEファイルに埋め込めばよいらしいです。
the Visual C++ linker embeds a UAC fragment into the manifest of an application (Manifestについて1 より)
ほかにも、シェルスクリプト系の場合は管理者として実行したコマンドプロンプトから実行する1か、runasコマンドを使えばUACの制約を回避できます。
いい感じのフローチャートを見つけたので、貼っておきます。何というか、このチャートがあればこの記事は読まなくてもよいですね。。 。
(Manifestについて1 より)
Manifest
これで終わるのはさみしいので、少し凝った設定を考えます。通常ユーザーを使用しているとき、管理者になることなくUACを回避することはできないでしょうか。
つまり、管理者として実行だと確かにUACの制約から逃れられるのですが、Administratorが持つすべての特権が与えられるので良くないです。さらに、管理者用アカウントの認証情報も必要です。なので、管理者に昇格(elevate)することなくUACを回避する2方法が欲しくなります。
これには、Manifestで/MANIFESTUAC:level=highestAvailable
とすればよいらしいです。
The application will run with the highest permission level that it can. (Manifestについて1 より)
これができると、さらに面白いことができます。Windowsでは管理者といえど与えられている特権には(デフォルトでは)限りがあります。そこで、管理者にも割り当てられていない特権を割り当てたユーザーを作り、そのユーザーでhighestAvailableなアプリケーションを実行すれば、管理者にその特権を割り当てるよりも安全に実行することができます。
ところで、UACで制限されている特権のうち、一部の特権のみ許可するにはどうすればよいのでしょうか3。(単なる問題提起です)
参考
- UACの概要: https://www.atmarkit.co.jp/ait/articles/1006/11/news107.html
- Manifestについて1: https://docs.microsoft.com/en-us/cpp/security/how-user-account-control-uac-affects-your-application?view=vs-2019
- Manifestについて2: https://docs.microsoft.com/en-us/previous-versions/bb756929(v=msdn.10)?redirectedfrom=MSDN
- Manifestについて3: https://www.codeproject.com/Articles/17968/Making-Your-Application-UAC-Aware
-
これが有効なのは、アクセストークンが子プロセスに受け継がれるからです。(参考: Windows セキュリティ・メカニズム入門) ↩
-
UACは通常ユーザーにも適用されます。管理者と通常ユーザーの差はそんなにありません。(参考: Windows OS入門 第一回) 通常ユーザーに対しても、Local Security Managerを使えば種々の特権を割り当てられますが、そうした特権はUACにより、デフォルトでは与えられません。 ↩
-
ご存じの方がいらっしゃいましたら、コメントしていただけると助かります。 ↩