レガシ アプリの AppContainer

AppContainer 環境は、リソースのセキュリティを提供するためにレガシ アプリに使用できる制限の厳しいプロセス実行環境です。 AppContainer アプリのプロセスとその子プロセスは、軽量のアプリ コンテナー内で実行されます。このコンテナーは、それらに対して明示的に許可されたリソースにのみアクセスできます。 また、ファイル システムとレジストリの仮想化を使用して分離されています。 その結果、AppContainer に実装されたアプリをハッキングして、限定的に許可されているリソース以外のリソースに対して悪意のあるアクションが実行されることはありません。

AppContainer は、パッケージ化されたアプリとパッケージ化されていないアプリの両方で、優れた安全なエンジニアリング方式です。

ヒント

AppContainer は (Windows 8 のリリース以前は) もともと LowBox という名前でした。 そのレガシ名は、NtCreateLowBoxToken などの API 名で確認できます。

パッケージ アプリ

MSIX を使用してパッケージ化されたアプリを取得し、AppContainer 環境で実行するように簡単に構成できます。 ユニバーサル Windows プラットフォーム (UWP) アプリは、自動的に AppContainer アプリになります。 ただし、MSIX と共にパッケージ化されたデスクトップ アプリを AppContainer アプリとして構成することもできます。 MSIX を使用してパッケージ化する場合、AppContainer を使用するのは特に簡単です。 詳細、シナリオ、構成例については、「MSIX AppContainer アプリ」を参照してください。

非パッケージ アプリ

パッケージ化されていないアプリも、アプリ コンテナーで実行できます。 アプリ コンテナーにプロセスを作成するには、AppContainer 定義 (またはプロファイル) が必要です。 そのため、パッケージアプリで AppContainer を使用する方が簡単です。 ユーザーのパッケージを登録すると、デプロイ スタックは、必要な AppContainer プロファイル (CreateAppContainerProfile など) を作成するために特定の Win32 API を呼び出します。 また、ユーザーのパッケージの登録を解除すると、AppContainer プロファイルを削除する処理 (DeleteAppContainerProfile) がデプロイ スタックによって実行されます。 アプリをパッケージ化していない場合は、それらの Win32 API を自分で呼び出して同様の操作を行う必要があります。しかし、それは複雑になる可能性があります。

整合性の低いレベルを使用したパッケージ化されていないほとんどのアプリでは、制約付き実行環境を提供するためのより優れた方法として AppContainer が使用されるようになりました。

アプリ コンテナーで実行されているパッケージ化されていないプロセスが CreateProcess を呼び出すと、通常、子プロセスは親のトークンを継承します。 そのトークンには、整合性レベル (IL) とアプリ コンテナー情報が含まれます。 値が elevated/medium/low/appContainer のいずれかである 1 つの軸として考えないことをお勧めします。 代わりに、アプリ コンテナーに存在するかどうかは、2 つ目の直交プロパティです。 つまり、アプリ コンテナー内にいる場合、整合性レベル (IL) は常に low になります。

AppContainer 環境を使用する利点

AppContainer 環境の主な目的は、他のアプリとの互換性を維持しつつ、アプリケーションの状態をシステムの状態からできるだけ分離することです。 Windows では、実行時にファイル システムとレジストリに加える特定の変更を検出してリダイレクトすることで実現します (仮想化と呼ばれます)。 AppContainer アプリでは、独自の仮想レジストリと仮想アプリケーション データ フォルダーに書き込みが行われます。そのデータは、アプリのアンインストール時またはリセット時に削除されます。 他のアプリから AppContainer アプリの仮想レジストリまたは仮想ファイル システムにアクセスすることはできません。

そのため、AppContainer 環境は、アプリのセキュリティで保護されたサンドボックスを提供します。 特定のアクセス許可なしで、ハードウェア、ファイル、レジストリ、その他のアプリ、ネットワーク接続、ネットワーク リソースへのアクセスからアプリを分離する。 個々のリソースは、他のリソースを公開せずに対象にすることができます。 さらに、ユーザー ID は、ユーザーとアプリを連結した一意の ID を使用して保護されます。およびリソースは、最小特権モデルを使用して付与されます。 これにより、他のリソースにアクセスするためにユーザーになりすましているアプリからさらに保護されます。

アプリ コンテナーでの実行をテストするコード例

C# または C++ プロジェクトでは、以下のコード例の適切な 1 つを使用して、プロセスがアプリ コンテナー内で実行されているかどうかを判断できます。 コードの実行後、isAppContainer の値が 0 以外 (または true) の場合、プロセスはアプリ コンテナー内で実行されています。

C# (P/Invoke)

[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetCurrentProcess();

[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool OpenProcessToken(
    IntPtr ProcessHandle,
    UInt32 DesiredAccess,
    out IntPtr TokenHandle);

[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetTokenInformation(
    IntPtr TokenHandle,
    uint TokenInformationClass,
    out uint TokenInformation,
    uint TokenInformationLength,
    out uint ReturnLength);

UInt32 TOKEN_QUERY = 0x0008;
IntPtr tokenHandle;

if (!OpenProcessToken(
    GetCurrentProcess(),
    TOKEN_QUERY,
    out tokenHandle))
{
    // Handle the error.
}

uint isAppContainer;
uint TokenIsAppContainer = 29;
uint tokenInformationLength = sizeof(uint);

if (!GetTokenInformation(
    tokenHandle,
    TokenIsAppContainer,
    out isAppContainer,
    tokenInformationLength,
    out tokenInformationLength))
{
    // Handle the error.
}

C++ (WIL)

この例では、Windows 実装ライブラリ (WIL) を使用します。 WIL をインストールするための便利な方法は、Visual Studio で、[プロジェクト]>[NuGet パッケージの管理...]>[参照] とクリックし、検索ボックスに「Microsoft.Windows.ImplementationLibrary」と入力するか貼り付けます。検索結果の項目を選択し、[インストール] をクリックしてそのプロジェクトにパッケージをインストールします。

#include <wil\token_helpers.h>
...
bool isAppContainer = wil::get_token_is_app_container();

関数 wil::get_token_is_app_container_nothrowwil::get_token_is_app_container_failfast は、代替のエラー処理戦略を提供します。 詳細については、wil\token_helpers.h を参照してください。

C++ (canonical)

#include <windows.h>
...
HANDLE tokenHandle{};
DWORD isAppContainer{};
DWORD tokenInformationLength{ sizeof(DWORD) };

if (!::OpenProcessToken(
    GetCurrentProcess(),
    TOKEN_QUERY,
    &tokenHandle))
{
    // Handle the error.
}

if (!::GetTokenInformation(
    tokenHandle,
    TOKEN_INFORMATION_CLASS::TokenIsAppContainer,
    &isAppContainer,
    tokenInformationLength,
    &tokenInformationLength
))
{
    // Handle the error.
}

このセクションの内容

レガシ アプリに AppContainer を使用する方法の詳細については、次のトピックを参照してください。

トピック 説明
AppContainer の分離 分離は、AppContainer 実行環境の主な目標です。 不要なリソースやその他のアプリからアプリを分離することで、悪意のある操作の機会が最小限に抑えられます。 最小特権に基づいてアクセス権を付与することで、アプリとユーザーは自分の権限を超えてリソースにアクセスできなくなります。 リソースへのアクセスを制御すると、プロセス、デバイス、およびネットワークが保護されます。
AppContainer を実装する AppContainer は、プロセス トークンに新しい情報を追加し、SeAccessCheck() を変更して、レガシの未変更のアクセス制御リスト (ACL) オブジェクトがすべて AppContainer プロセスからのアクセス要求を既定でブロックするようにし、AppContainers で使用できる必要があるオブジェクトを再 ACL するよって実装されます。