Report CVE-2023-28218
バグ概要
Windows カーネルで特権昇格につながるバグ。このバグはドライバ Windows Ancrillary Function Driver for WinSock (AFD.sys) に存在する。このバグは 2023/04/11 のパッチで修正された。CVSS:3.1 7.0 / 6.1 のスコアを持ち、Important と評価されている。
バグの説明
- バグの種類:
Double fetch と Integer overflow により pool overflow が発生する。
- バグは関数
Afd!AfdComputeCMSGLength と Afd!AfdCopyCMSGBuffer 内で発生する。

これら2つの関数はどちらも v82 を入力パラメータとして受け取る。v82 は usermode が制御するアドレスである。関数 Afd!AfdComputeCMSGLength では、このアドレスが直接参照されて値が取得される。その後、CMSG バッファの length の値が計算され、戻り値として返される。その後、このサイズに基づいてプールが割り当てられる。入力パラメータ a1 と a2 を制御することで、パラメータ a3 に返されるサイズを制御できる。

関数 Afd!AfdCopyCMSGBuffer では、アドレス v82 が直接参照されて値が取得される。いくつかのチェックを経て、この値は memmove 操作のサイズとして使用される。

この関数には Integer overflow のバグがあり、2つの関数がどちらも usermode 側のアドレスから直接フェッチするため、実行中にその値を変更できる。これにより、memmove 時のサイズ値が非常に大きくなる。アクセスできないメモリ領域へのコピーが発生すると、try catch が実行される。しかし、それ以前のメモリ領域のコピーはすでに行われている。これにより、意図したサイズでコピーを行うことができる。

- POC をトリガーするには、まず
type パラメータを SOCK_DGRAM とした socket を作成する必要がある。次に、この socket のハンドルを bind 関数のパラメータとして使用する。最後に2つのスレッドを作成し、1つのスレッドは IOCTL 0x120D3 で DeviceControl を呼び出し続ける。いくつかのチェックを回避するために適切な userbuffer をセットアップする。もう1つのスレッドは、上記の2つの関数のパラメータとなる usermode アドレスに保存された値を変更し続ける。
エクスプロイト
- このバグを使用すると、non-paged NX pool を任意のサイズでオーバーフローさせることができ、データは usermode 側から完全に制御可能である。
- 攻撃手法としては、まず多数の
Namedpipe オブジェクトをスプレーし、いくつかのオブジェクトを解放してヒープ上にホールを作成する。その後、Afd!AfdComputeCMSGLength 関数から計算されたサイズでプールを作成する。このサイズは Namedpipe オブジェクトのサイズと一致させる必要がある。そうすると、プールは解放されたばかりのオブジェクトに割り当てられる。このバグを使用して隣接する Namedpipe オブジェクトをオーバーフローさせ、Namedpipe のメカニズムを利用してカーネルメモリの読み書き権限を取得する。system プロセスの token を読み取り、現在のプロセスの token に書き込む。
影響範囲
- Windows Server 2012 R2 (Server Core installation) build 6.3.9600.20919 より前
- Windows Server 2012 R2 build 6.3.9600.20919 より前
- Windows Server 2012 (Server Core installation) build 6.2.9200.24216 より前
- Windows Server 2012 build 6.2.9200.24216 より前
- Windows Server 2008 R2 for x64-based Systems Service Pack 1 (Server Core installation) build 6.1.7601.26466 より前
- Windows Server 2008 R2 for x64-based Systems Service Pack 1 build 6.1.7601.26466 より前
- Windows Server 2008 for x64-based Systems Service Pack 2 (Server Core installation) build 6.0.6003.22015 より前
- Windows Server 2008 for x64-based Systems Service Pack 2 build 6.0.6003.22015 より前
- Windows Server 2008 for 32-bit Systems Service Pack 2 (Server Core installation) build 6.0.6003.22015 より前
- Windows Server 2008 for 32-bit Systems Service Pack 2 build 6.0.6003.22015 より前
- Windows Server 2016 (Server Core installation) build 10.0.14393.5850 より前
- Windows Server 2016 build 10.0.14393.5850 より前
- Windows 10 Version 1607 for x64-based Systems build 10.0.14393.5850 より前
- Windows 10 Version 1607 for 32-bit Systems build 10.0.14393.5850 より前
- Windows 10 for x64-based Systems build 10.0.10240.19869 より前
- Windows 10 for 32-bit Systems build 10.0.10240.19869 より前
- Windows 10 Version 22H2 for 32-bit Systems build 10.0.19045.2846 より前
- Windows 10 Version 22H2 for ARM64-based Systems build 10.0.19045.2846 より前
- Windows 10 Version 22H2 for x64-based Systems build 10.0.19045.2846 より前
- Windows 11 Version 22H2 for x64-based Systems build 10.0.22621.1555 より前
- Windows 11 Version 22H2 for ARM64-based Systems build 10.0.22621.1555 より前
- Windows 10 Version 21H2 for x64-based Systems build 10.0.19044.2846 より前
- Windows 10 Version 21H2 for ARM64-based Systems build 10.0.19044.2846 より前
- Windows 10 Version 21H2 for 32-bit Systems build 10.0.19044.2846 より前
- Windows 11 version 21H2 for ARM64-based Systems build 10.0.22000.1817 より前
- Windows 11 version 21H2 for x64-based Systems build 10.0.22000.1817 より前
- Windows 10 Version 20H2 for ARM64-based Systems build 10.0.19042.2846 より前
- Windows 10 Version 20H2 for 32-bit Systems build 10.0.19042.2846 より前
- Windows 10 Version 20H2 for x64-based Systems build 10.0.19042.2846 より前
- Windows Server 2022 (Server Core installation) build 10.0.20348.1668 より前
- Windows Server 2022 build 10.0.20348.1668 より前
- Windows Server 2019 (Server Core installation) build 10.0.17763.4252 より前
- Windows Server 2019 build 10.0.17763.4252 より前
- Windows 10 Version 1809 for ARM64-based Systems build 10.0.17763.4252 より前
パッチ
- バグは、2つの旧関数を2つの新関数に置き換えることで修正された。旧関数の名前の末尾には
_old が付加されている。これらの新しい関数は。2つの新関数では、依然として double fetch が存在するが、フェッチされた値は使用前にチェックされる。Rtl 関数は算術演算を置き換えるために使用され、Integer overflow を防いでいる。
結論
- このバグは影響範囲が非常に広く、多くのシステムを脅かす。ただし、実行中のエクスプロイトペイロードは、ヒープスプレーにより Windows がクラッシュする小さな失敗率がある。また、cmd プロセスの権限を System に昇格させた後、このプロセスを終了すると、エクスプロイト中に Namedpipe オブジェクトが破損しているため、Windows がクラッシュする。
添付ファイル
- 最小限の POC

- エクスプロイト POC
