2018年12月、「SandboxEscaper」というエイリアスで知られるハッカーが Windows エラー報告 (Windows Error Reporting, WER) コンポーネントに存在するゼロデイ脆弱性を公開しました。この公開内容をさらに深く掘り下げた結果、筆者はその脆弱性とはべつにもうひとつのゼロデイ脆弱性があることを発見しました。その脆弱性はシステム特権昇格に悪用される可能性があるもので、Microsoft のアドバイザリによれば、2019年5月にパッチがリリースされるまで攻撃者たちが当該脆弱性をゼロデイとして悪用していたようです。
そこで本稿では、当該脆弱性がどのような機序で悪用されるのかを見ていきます。
Microsoft WINDOWS エラー報告 (WINDOWS ERROR REPORTING)とは
Windows エラー報告 は、イベントに基づいて柔軟なフィードバックを行うためのしくみで、Windows で検出可能なハードウェア/ソフトウェア関連の障害情報を収集し、その情報を Microsoft に報告し、ユーザーに利用可能な解決策を提供するよう設計されています。
たとえば、Windows がシステム クラッシュや障害に遭遇した場合、エラー レポートが生成され、Windows エラー報告のレポート キュー ディレクトリにそのレポートが保存されます (C:\ProgramData\Microsoft\Windows\WER\ReportQueue)。このディレクトリ以下には、レポートごとのサブディレクトリと関連メタデータを含む一意の Report.wer INI ファイルが置かれます。すべてのプロセスが障害報告できるよう、ReportQueue ディレクトリは、どのユーザーでも書き込みが可能です (下図参照)。

図 1 Windows エラー報告のキュー ディレクトリ
生成後のレポートは、さらなる分析のために Microsoft に送信する必要があります。この情報のやりとりをトリガーする方法には何種類かあって、その 1 つがタスク スケジューラの Windows Error Reporting\QueueReporting スケジュール タスクを利用する方法です。このタスクはセキュリティの観点で見て興味深く、次のような特徴をもっています。
- タスクの [セキュリティ オプション] セクションで定義されているとおり、システム権限で実行される
- タスクを要求時に実行できる
- 決め打ちのコマンドライン引数を指定して専用バイナリ コードを実行する (wermgr.exe -upload)

図 2 Windows エラー報告のタスク スケジュール
実行されると、wermgr.exe は保留になっているレポート ファイルやディレクトリとやり取りをする、つまりレポート ファイルを読み取り、解析し、ほかのディレクトリにコピーし、ときには削除することもあります。要するにここには、誰にでも書き込み権限のあるファイルにアクセス可能な、最上位特権で動作するコンポーネントがあり、注意して実装しないと深刻なセキュリティ脆弱性が生じる可能性がある、ということになります。
ファイルシステム リンクの悪用
Windows は、さまざまな種類のファイルシステム リンクをサポートしています。リンクを使用すれば、あるファイルやディレクトリがべつの意図したファイルやディレクトリを指すようにすることができます。ごく簡単に言うなら、リンクはいったんスキャン・再解析された後は、ユーザーを意図したべつのパスにリダイレクトするようになります。セキュリティの観点から見ると、最大の脅威はハードリンクとマウントポイントの悪用によるものでしょう。というのもこれらを悪用すれば、ユーザーは、もともと書き込み権限を持っていないファイルやディレクトリにもリンクできるようになるからです。
たとえば次の例は、kernel32.dll に対する書き込み権限を持っていないユーザーが、c:\temp\Dir\x.dll と C:\Windows\System32\kernel32.dll の間にリンクを作成する様子を示しています。ハッカーにとっては、より高い特権をもつコンポーネントにリダイレクトさえできればそれで用が足りるのです。それだけあれば、機微な重要ファイルの読み書きに加え、それらの削除すら可能になります。

図 3 ユーザーが書き込み権限を持っていないファイルにハードリンクを作成する様子
Windows エラー報告の特権の昇格の脆弱性について
かいつまんで言えば、ハッカーは、Windows エラー報告の機能を悪用して、先に説明したファイルシステムのリンクを使ってレポート ディレクトリ内のファイルをコンピュータ上のべつの意図したファイルにリンクすることで、自分が読み取り・書き込み・削除をしたいほかのファイルに対し、そのための権限を割り当てることができるようになります。
もうすこし詳しく説明するなら、当該脆弱性は次のようにして悪用されます。
- ステップ 1: wermger.exe がレポート ディレクトリ以下すべてのファイルを 1 つずつ解析し、それらを Microsoft に送信します。
- ステップ 2: wermger.exe が Report.wer INI ファイルの破損を検出した場合、当該ファイルを削除するためにプロセス実行者権限を付与してファイルの DACL (discretionary access control list、随意アクセス制御リスト) プロパティを変更し、そののちに最終的な削除を行います。
- エクスプロイト: ハッカーは、「wermger.exe によるファイルの DACL 読み取り」から「当該ファイルに削除権限が付与されるまで」までのごく短かい隙を突きます。攻撃者がそうした破損ファイルとシステム上にあるべつのファイルとの間にリンクを作成した場合、DACL 読み取り後に wermgr.exe がほかのファイルのセキュリティ記述子を誤って変更してしまいます。これがきわめて、きわめて深刻なシナリオであることに疑いの余地はないでしょう。
ステップ 1:
最初に wermgr.exe -upload が行うのは、wermgr!DoCoreUpload 関数の呼び出しです。wermgr!DoCoreUpload 関数は、ReportQueue 以下のすべてのサブディレクトリを一覧する関数です。この関数が、エラーレポートを読み取って、Microsoft に送信します。
int64 DoCoreUpload(/* ... */) {
/* ... */
Ret = WerpSubmitReportFromStore(ReportPath, /* ... */);
if (Ret >= 0) {
/* Report successfully uploaded */
} else {
if (Ret == ERROR_FILE_CORRUPT) {
DeleteCorruptedReportFromStore(ReportPath);
}
}
}