ユーザーインターフェイス特権の分離
ユーザーインターフェイス特権の分離 (英語: User Interface Privilege Isolation, UIPI)[1] とは、Windows Server 2008/Vista以降に、シャッターアタック(Shatter Attack、壊滅的攻撃)を防ぐために導入されたセキュリティ機能である。Windows NT 4.0以降、Object Managerを介して生成されるオブジェクトにはセキュリティ記述子が与えられ、そうしたオブジェクトへのアクセス制御は可能であったが、ウィンドウオブジェクトにはセキュリティ記述子は与えられず、ウィンドウ自体へのセキュリティ制御はできなかった。
UIPIと必須整合性制御により、同じ対話型デスクトップ内において、低い整合性で実行されているプロセスは、より高い整合性で実行されているプロセスに対して、DLLインジェクションやウィンドウメッセージAPI(SendMessage/PostMessage等)など、任意のコードを他プロセスに実行させることのできる操作を実行できない。
機能
[編集]
Windowsでは、任意のウィンドウオブジェクトを取得してそのオブジェクトに対してデータを送信する(WM_SETTEXT)ことができるが、言い換えれば、悪意のあるデータを送りつけることが可能である。次の例において、もしメモ帳のプロセスが高い整合性レベルで実行されている場合、UIPIはこうした書き込みをブロックする[2]。
// ウインドウクラスを元に、メモ帳のウインドウを検索
HWND hwndNotepad = FindWindow(L"notepad", NULL);
// メモ帳のウインドウからエディトコントロールを取得
HWND hWndEdit;
EnumChildWindows(hWndEdit, EnumChildProc, (LPARAM)&hWndEdit);
// エディトコントロールに任意のテキストを設定
BOOL bResult = SendMessage(hWndEdit, WM_SETTEXT, 0, (LPARAM)L"text");
ただし、WM_NULL、WM_MOVE、WM_SIZE、WM_GETTEXT、WM_GETTEXTLENGTH、WM_GETHOTKEY、WM_GETICON、WM_RENDERFORMAT、WM_DRAWCLIPBOARD、WM_CHANGECBCHAIN、WM_THEMECHANGEDはUIPIのブロックする対象ではない[2]。特に、WM_GETTEXTがブロックされないということは、高ILで実行されているプロセスのウィンドウオブジェクトのデータを読み取ることはできるということである[2]。
WCHAR wszBuffer[1024];
bResult = SendMessage(hWndEdit, WM_GETTEXT, sizeof(wszBuffer) / sizeof(WCHAR), (LPARAM)wszBuffer);
シャッター攻撃において、バッファーフローを引き起こせるメッセージはWM_COPYDATAとWM_DROPFILESなどがある。例えば、送信側はWM_COPYDATAの自身のサイズ(cbData)を自由に設定できるため、もし受信側が受け取るサイズを静的に定義しているとオーバーフローが起こる可能性がある。当然、UIPIはこれを防ぐため導入されたため、このようなメッセージを低ILプロセスから高ILプロセスに送ることはできない[2]。
WCHAR wszData[] = L"message";
COPYDATASTRUCT data = { 0 };
data.cbData = sizeof(wszData); // 0xFFFFFFFFでもよい。
data.lpData = wszData;
SendMessage(hWndTarget, WM_COPYDATA, (WPARAM)hWnd, (LPARAM)&data);
無効化
[編集]特定の種類のメッセージのフィルターを無効化
[編集]整合性レベル「中(Medium)」以上のプロセスは、ChangeWindowMessageFilterExを使用して、特定の種類のメッセージを許可することができる[2]。
マニフェストによる完全無効化
[編集]例えば、osk.exeは画面にキーボードUIを表示し、 ユーザーがキーをクリックすると、その入力を背後のウインドウに送信する。 もし、背後のウインドウが昇格したプロセスによって作成されていても、UIPIによってブロックされるべきではない[2]。
こうしたUIアクセシビリティソフトウェアのような、他のソフトウェアのUIにアクセスするソフトウェアはUIPIが障壁となる。そのため、Windowsは以下の条件を満たしている場合に限り、UIPIの無効化を提供する[2]。
- デジタル署名されている。
%SystemRoot%もしくは%ProgramFiles%にインストールされている。- アプリケーションマニフェストで
uiAccess値がtrueである。 <requestedExecutionLevel level="..." uiAccess="true" />