
CVE-2020-1362 の解説
WalletService の特権昇格バグは、先月の Patch Tuesday で修正されました。そのうちの 1 つが CVE-2020-1362 です。この脆弱性は、サービス内の範囲外 (out-of-bounds) バグを利用するものです。ここでは、それを悪用するためのテクニックを共有します。
walletservice.dll 内の以下の関数のバイナリ解析を実施しました。
SetGroup 関数は、ユーザーが制御するオフセットのメモリに、ユーザーが制御するデータを書き込みました。
signed __int64 __fastcall Wallet::WalletCustomProperty::SetGroup(__int64 this, int a2, int a3, int a4)
{
signed __int64 result; // rax
result = 0i64;
if ( a2 == 1 )
{
if ( a3 & 0xFFFFFFDF )
return 0x80070057i64;
}
else if ( a3 == 0x20 )
{
return 0x80070057i64;
}
if ( a4 == -1 )
{
*(_DWORD *)(this + 8i64 * a2 + 0x74) = 0;
*(_DWORD *)(this + 8i64 * a2 + 0x78) = 0x7FFFFFFF;
}
else
{
*(_DWORD *)(this + 8i64 * a2 + 0x74) = a3;
*(_DWORD *)(this + 8i64 * a2 + 0x78) = a4;
}
return result;
}
この関数は、ユーザーが制御できるオフセットの範囲をチェックしていないことがわかります。これが脆弱性が発生する箇所です。
これで、範囲外のメモリに書き込めるようになります。確認すると、同じクラスに BSTR を設定および取得する関数があることがわかります。
したがって、oobw を通じて BSTR へのポインタを簡単に変更し、任意のアドレスを読み書きできるようになります。
WWW (write-what-where) を手に入れたら、ヒープ上の Wallet::WalletCustomProperty オブジェクトの vtable を書き換えて RIP を制御できます。当初、oobw で直接書き換えようとしましたが、oobw は 8 バイトにアラインされていないことがわかりました。そのため、レースコンディションを利用して vtable ハイジャックを達成するには、2 回書き込む必要があります。しかし、これによりエクスプロイトが不安定になる可能性があります。これを回避する方法は他にもいくつかあります。しかし、私たちの POC では、別の情報漏えい脆弱性 (CVE-2020-1361) を使用してヒープアドレスを漏えいさせ、www を使用して vtable を直接書き込みました。ちなみに、CVE-2020-1361 は情報漏えい脆弱性としてマークされていますが、実際には EOP を達成するために使用できます。これについては、後日 writeup を作成する予定です。
任意の関数の実行から任意のコード実行へと進むために、dxgi.dll 内の ATL::CComObject<CDXGIAdapter>::`vector deleting destructor 関数を利用しました。この関数は loadlibraryEx 関数を呼び出し、loadlibraryEx の最初のパラメータとしてグローバルポインタを取ります。これにより、カスタム DLL をロードして任意のコード実行を達成できます。
POC ディレクトリにサンプル POC を用意しています。
この脆弱性を通じて、medium から NT AUTHORITY\system への特権昇格を達成できます。
Windows 10.0.18363.815, x64 でテスト

Haoran Qin
Qihoo 360 の Zhiniang Peng (@edwardzpeng)
Apr 10 2020: 脆弱性を報告
Apr 21 2020: MSRC が調査し、バグを確認
Jul 14 2020: パッチ公開
Jul 17 2020: Writeup 公開