低い整合性レベルで実行するアプリケーションの設計
低い整合性レベルでアプリケーション プロセスを実行する簡単な方法は、実行可能プログラム ファイルの整合性レベルを低い整合性に設定することです。 そのイメージ ファイルが起動されると、アプリケーション プロセスは低い整合性レベルで開始されます。 たとえば、整合性の低いプロセスで Windows Calculator アプリケーションを実行するとします。
整合性が低いcalc.exeを実行するには
c:\Windows\system32\calc.exeのコピーを一時フォルダーに作成します。
icacls プログラムを使用して、icacls コマンドを使用して、一時ファイルの整合性レベル (lowcalc.exe) を低い整合性に設定します。
icacls lowcalc.exe /setintegritylevel Low
calc.exeの整合性の低いバージョンを実行します。
次の図は、整合性の低いプロセスで Windows Calculator を実行する手順を示しています。
図 9 低整合性での Windows 電卓の起動
プロセス エクスプローラーを使用して、イメージ ファイル (lowcalc.exe) が実際に低い整合性で実行されていることを確認できます。 [整合性レベル] 列はイメージの右側にあります。
図 10 低計算プロセス
整合性の低いプロセスでは、すべてのアプリケーション プログラムが適切に実行されるわけではありません。 整合性の低いプロセスでは、ファイル システムまたは HKCU の下のレジストリのユーザーのローカル プロファイル領域のほとんどの領域に書き込みアクセス権がありません。 プログラムが望ましくない悪意のあるソフトウェアである場合、低整合性プロセスがユーザー プロファイルへの書き込みアクセス権を取得できないことは良いことです。 ただし、保護モードのインターネット エクスプローラーなどのアプリケーションでは、アプリケーションのすべての機能を正しく動作させるには、いくつかの再設計が必要になる場合があります。
Sysinternals.com からのプロセス モニターなどの便利なツールを使用して、アプリケーションが書き込みアクセスに現在使用しているファイルリソースとレジストリ リソースを把握し、整合性の低い状態で実行すると失敗します。
完全に低い整合性で実行するようにアプリケーションを変更することはできますが、アプリケーションの一部の機能は、中程度の整合性プロセスで実装されている場合にのみ適切に機能する場合があります。 低整合性で実行されているアプリケーションは、たとえば、インターネットから信頼されていないデータを処理するなど、整合性の低いプロセスでアプリケーションの一部を持つ場合があります。 アプリケーションの別の部分は、中程度の整合性の "ブローカー" プロセスに実装して、ユーザーが開始する少数のアクションセットを処理できます。 アプリケーション内の低整合性プロセスと中整合性プロセス間の通信は、さまざまな IPC メカニズムを使用して処理できます。 アプリケーションの中整合性部分では、整合性の低いプロセスのすべてのデータとコードが信頼できないと想定する必要があります。
保護モードのインターネット エクスプローラーは、整合性の低いプロセスで実行するように再設計された 1 つのアプリケーションです。 保護モードのインターネット エクスプローラーの詳細については、「保護モードのインターネット エクスプローラーhttps://go.microsoft.com/fwlink/?LinkId=90931について」を参照してください。
整合性が低いアプリケーションを設計するためのメイントピックは次のとおりです。
- 低い整合性で子プロセスを開始する
- 低整合性アプリケーションの書き込み可能な場所
- 低整合性プロセスと上位レベルプロセス間の通信
低い整合性でプロセスを開始する
既定では、子プロセスは親プロセスの整合性レベルを継承します。 低整合性プロセスを開始するには、CreateProcessAsUser 関数を使用して、低整合性アクセス トークンを使用して新しい子プロセスを開始する必要があります。 中整合性プロセスから低整合性プロセスを開始するには、新しいプロセスを低整合性として明示的に開始する必要があります。
整合性の低いプロセスを開始するには
現在のプロセスのハンドルを複製します。これは、中程度の整合性レベルです。
SetTokenInformation を使用して、アクセス トークンの整合性レベルを Low に設定します。
CreateProcessAsUser を使用して、整合性の低いアクセス トークンへのハンドルを使用して新しいプロセスを作成します。
CreateProcessAsUser は、新しい子プロセスのセキュリティ記述子と、アクセス トークンのセキュリティ記述子を、低整合性アクセス トークンの整合性レベルと一致するように更新します。
次のコード サンプルは、このプロセスを示しています。
void CreateLowProcess()
{
BOOL fRet;
HANDLE hToken = NULL;
HANDLE hNewToken = NULL;
PSID pIntegritySid = NULL;
TOKEN_MANDATORY_LABEL TIL = {0};
PROCESS_INFORMATION ProcInfo = {0};
STARTUPINFO StartupInfo = {0};
// Notepad is used as an example
WCHAR wszProcessName[MAX_PATH] =
L"C:\\Windows\\System32\\Notepad.exe";
// Low integrity SID
WCHAR wszIntegritySid[20] = L"S-1-16-1024";
PSID pIntegritySid = NULL;
fRet = OpenProcessToken(GetCurrentProcess(),
TOKEN_DUPLICATE |
TOKEN_ADJUST_DEFAULT |
TOKEN_QUERY |
TOKEN_ASSIGN_PRIMARY,
&hToken);
if (!fRet)
{
goto CleanExit;
}
fRet = DuplicateTokenEx(hToken,
0,
NULL,
SecurityImpersonation,
TokenPrimary,
&hNewToken);
if (!fRet)
{
goto CleanExit;
}
fRet = ConvertStringSidToSid(wszIntegritySid, &pIntegritySid);
if (!fRet)
{
goto CleanExit;
}
TIL.Label.Attributes = SE_GROUP_INTEGRITY;
TIL.Label.Sid = pIntegritySid;
//
// Set the process integrity level
//
fRet = SetTokenInformation(hNewToken,
TokenIntegrityLevel,
&TIL,
sizeof(TOKEN_MANDATORY_LABEL) + GetLengthSid(pIntegritySid));
if (!fRet)
{
goto CleanExit;
}
//
// Create the new process at Low integrity
//
fRet = CreateProcessAsUser(hNewToken,
NULL,
wszProcessName,
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&StartupInfo,
&ProcInfo);
CleanExit:
if (ProcInfo.hProcess != NULL)
{
CloseHandle(ProcInfo.hProcess);
}
if (ProcInfo.hThread != NULL)
{
CloseHandle(ProcInfo.hThread);
}
LocalFree(pIntegritySid);
if (hNewToken != NULL)
{
CloseHandle(hNewToken);
}
if (hToken != NULL)
{
CloseHandle(hToken);
}
return fRet;
}
整合性が低い書き込み可能な場所
Windows Vista には、整合性の低いアプリケーションの書き込みアクセスを許可するために、低い必須ラベルが割り当てられている特定のファイルとレジストリの場所があります。 表 10 に、これらの書き込み可能な場所を示します。
表 10 低い必須ラベルに対して書き込み可能な場所
場所 | 書き込み可能領域 |
---|---|
レジストリ |
整合性の低いプロセスでは、HKEY_CURRENT_USER\Software\AppDataLowの下にサブキーを書き込んで作成できます |
ファイル システム |
整合性の低いプロセスでは、%USER PROFILE%\AppData\LocalLow の下にサブフォルダーを書き込んで作成できます |
リソースの必須ラベルを下げる
潜在的なセキュリティ リスクのため、入力を受け入れるか、整合性の低いプロセスでリソースを共有するように、より高い整合性プロセスを設計することはお勧めしません。 整合性の低いプロセスでは、悪意のある動作が試みられます。 ただし、設計上、この操作を行う必要がある場合があります。
注意
整合性の低いプロセスでリソースからの入力を受け入れるか、リソースを共有するアプリケーションでは、整合性の低いプロセスが提供するデータを信頼できないと想定し、適切な検証を実行する必要があります。 たとえば、保護モードのインターネット エクスプローラーでは、インターネット エクスプローラー User Broker プロセスから [名前を付けて保存] ダイアログ ボックスが表示されます。 これにより、ユーザーは保護モードのインターネット エクスプローラーよりも高い権限で実行されるプロセスを使用してファイルを保存することを確認できます。
整合性の低いアプリケーションは、整合性の低いリソースにのみ書き込むことができるため、共有リソースの整合性レベルを下げる必要があります。
共有リソースの整合性レベルを下げるには
低い必須ラベルを定義する SDDL セキュリティ記述子を作成します。
SDDL 文字列をセキュリティ記述子に変換します。
低整合性属性をセキュリティ記述子に割り当てます。
共有リソースにセキュリティ記述子を割り当てます。
次のコード サンプルは、このプロセスを示しています。
#include <sddl.h>
#include <AccCtrl.h>
#include <Aclapi.h>
void SetLowLabelToFile()
{
// The LABEL_SECURITY_INFORMATION SDDL SACL to be set for low integrity
#define LOW_INTEGRITY_SDDL_SACL_W L"S:(ML;;NW;;;LW)"
DWORD dwErr = ERROR_SUCCESS;
PSECURITY_DESCRIPTOR pSD = NULL;
PACL pSacl = NULL; // not allocated
BOOL fSaclPresent = FALSE;
BOOL fSaclDefaulted = FALSE;
LPCWSTR pwszFileName = L"Sample.txt";
if (ConvertStringSecurityDescriptorToSecurityDescriptorW(
LOW_INTEGRITY_SDDL_SACL_W, SDDL_REVISION_1, &pSD, NULL))
{
if (GetSecurityDescriptorSacl(pSD, &fSaclPresent, &pSacl,
&fSaclDefaulted))
{
// Note that psidOwner, psidGroup, and pDacl are
// all NULL and set the new LABEL_SECURITY_INFORMATION
dwErr = SetNamedSecurityInfoW((LPWSTR) pwszFileName,
SE_FILE_OBJECT, LABEL_SECURITY_INFORMATION,
NULL, NULL, NULL, pSacl);
}
LocalFree(pSD);
}
}
アプリケーション プロセスでは、セキュリティ保護可能なオブジェクトの整合性を、アプリケーション プロセスの整合性レベル以下のレベルにのみ設定できます。
低整合性プロセスと高整合性プロセス間の通信
整合性の低いプロセスは、他のアプリケーションから完全に分離されているわけではありません。 他のプロセスと対話できます。 実際、何らかの形のコラボレーションがないと、整合性が低いアプリケーションが完全に壊れているように見える場合があります。
整合性の低いプロセスが整合性の高いプロセスと通信するために、一部の形式の IPC を使用できます。 Windows Vista のコンポーネントは、次の種類の通信をブロックします。
ほとんどのウィンドウ メッセージとプロセス フックは、UIPI によってブロックされます。
プロセスを開いて CreateRemoteThread を使用すると、プロセス オブジェクトの必須ラベルによってブロックされます。
書き込みアクセス用の共有メモリ セクションを開くのはブロックされます。
同期のためにより高い整合性プロセスによって作成された名前付きオブジェクトの使用は、既定の必須ラベルによってブロックされます。
COM サービスの実行中のインスタンスへのバインドはブロックされます。
ただし、整合性の低いプロセスと整合性の高いプロセスの間で、他の種類の通信を使用できます。 使用できる通信の種類は次のとおりです。クリップボード (コピーと貼り付け)
リモート プロシージャ呼び出し (RPC)
ソケット
ChangeWindowMessageFilter を呼び出すことによって、整合性の高いプロセスが低整合性プロセスからの受信を明示的に許可されているウィンドウ メッセージ
共有メモリ。高い整合性プロセスにより、共有メモリ セクションの必須ラベルが明示的に下がる
重要
これは特に危険であり、整合性の高いプロセスでは、共有セクションに書き込まれるすべてのデータを検証するように注意する必要があります。
COM インターフェイス。起動のアクティブ化権限は、整合性の低いクライアントからのバインドを許可するために、より高い整合性プロセスによってプログラムによって設定されます
名前付きパイプ。作成者がパイプの必須ラベルを明示的に設定して、整合性の低いプロセスへのアクセスを許可する
これらの通信メカニズムを使用すると、整合性の低いプロセスがブローカー プロセスなどの他のアプリケーション プロセスと対話できます。これは、特に、整合性の低いソースからの入力または呼び出しを受け入れるように設計されています。
整合性の低いプロセスが呼び出すインターフェイスを設計するための一般的なガイドラインは、呼び出し元または入力データを信頼することはありません。 中整合性ブローカーは、パスを指定してファイルを作成し、整合性の低いアプリケーションがインターフェイスを呼び出せるようにするためのインターフェイスを提供できます。 ただし、これにより、整合性が低いアプリを実行する目的は損なわれます。 より優れた設計は、整合性の低いプロセスで、中間整合性アプリケーションに共通のファイル ダイアログをユーザーに表示するように要求するインターフェイスを呼び出し、低整合性プロセスではウィンドウ メッセージを使用できません。 これにより、ユーザーが開くファイルまたは作成するファイルを参照して選択し、中整合性プロセスですべてのファイル操作が実行されます。 この種類の名前を付けて保存シナリオは、保護モードのインターネット エクスプローラーが独自のブローカー プロセスを使用して、ユーザーのプロファイル内のどこかに Web ページを保存する方法の例です。
多くのアプリケーション機能は、整合性の低いプロセスで正しく実行できます。 整合性が低いアプリケーションを実行するための一般的なツール セットはありません。 アプリケーションはそれぞれ異なっており、すべてのアプリケーションが低い整合性で実行する必要があるわけではありません。