エグゼクティブサマリー
Akamai の研究者は、根本原因を即座に分析するための新しい AI 機能を開発しました。このツールは、PatchDiff-AI と呼ばれる監視付きマルチエージェントシステムです。このブログ記事では、このツールを使用し、ほぼすべての Windows バージョンに影響を及ぼす CVE-2025-60719 の詳細な分析を行います。
脆弱性:競合状態が原因で発生する、Winsock の Windows Ancillary Function Driver(afd.sys)の Use-After-Free(UAF)脆弱性
影響:ローカル権限昇格。権限の低い攻撃者がカーネルメモリを操作してシステム権限を取得する可能性があります
根本原因:他の操作(Transfer、GetInformation、Connect など)が関連オブジェクトをアクティブに逆参照している間に、ソケットエンドポイントがバインド解除(解放)されるのをドライバーが防止できませんでした
修正:Microsoft は、重要な操作中にエンドポイントの状態を明示的にロックする同期バリアメカニズム(AfdPreventUnbind/AfdReallowUnbind)を追加しました
PatchDiff-AI ツールを使用することで、どのように影響の大きい Patch Tuesday の脆弱性の根本原因を迅速に分析でき、セキュリティチームがワンデイ脆弱性をより適切に検知して緩和できるようになるかをご確認ください。
脆弱性
CVE-2025-60719 は、Windows カーネル・ネットワーク・スタック(特に Winsock API の背後にある基盤である afd.sys)内の重大な欠陥です。攻撃に成功すると、低権限のプロセスがシステム権限を取得できるようになります。Akamai は AppContainer プロセス内で攻撃をテストしましたが、権限が不十分であるため失敗しました。
この脆弱性は、次のすべての Windows バージョンを含む多くの Windows 製品に影響します。
Windows Server — 2008 SP2(x86/x64)、2008 R2 SP1、2012、2012 R2、2016、2019、2022、2022 23H2、2025
Windows 11 — 23H2、24H2、25H2
Windows 10 — バージョン 1607、1809、21H2、22H2
その他のサポート終了バージョン
これほど幅広いバージョンに影響が及ぶと、アタックサーフェスが大幅に増大します。
根本原因分析
PatchDiff-AI を使用すれば、ベンダーの勧告に基づき、脆弱性を修正するセキュリティパッチを迅速に分析できます。ツールの分析結果によると、関連するコード変更には、メソッド AfdSocketTransfer*、AfdGetInformation、AfdBind、AfdConnect が含まれます。
詳しく見ると、この脆弱性の根本原因は、AFD エンドポイント構造(AFD_ENDPOINT)のライフサイクル管理と、オブジェクトポインタのフェッチと使用の間のアトミック性(同時操作同期)の欠如にあることがわかります。
変更内容
PatchDiff-AI ツールは、この脆弱性のコアロジックに直接関連する 1 つのコンポーネントを明らかにしました。それは、Windows のコアトランスポート層ネットワークサポートを実行する Ancillary Function Driver(afd.sys)です。これは Winsock インターフェースを提供し、ネットワークソケットを管理し、その他の I/O 関連機能を処理します。
このツール分析は、KB5068861 セキュリティ更新プログラムの一部として修正されたバージョン 10.0.26100.7171 に基づいており、KB5066835 セキュリティ更新プログラムの一部である脆弱なバージョン 10.0.26100.6899 との比較検証を行いました。
修正された機能は全部で 5 つあり、ツールはそのすべてをセキュリティ関連として分類しました。
AfdGetInformation 関数を分析すると、現在はバインド解除操作をブロックしてソケットが解放されないようにすることによって保護されているコードブロックを特定できます(図 1)。この変更はソケットのライフサイクルを参照し、その状態に干渉することを把握しているため、UAF 脆弱性に関連しているはずです。
Ancillary Function Driver の基礎知識
Ancillary Function Driver(afd.sys)の動作とその使用方法に関する包括的な記事がいくつかあります。手短に言うと、これは Winsock API を提供する Windows コンポーネントです。低権限のプロセスが TCP/IP やその他の通信プロトコルにネットワークスタックを使用できるようにするものです。
図 2 では、入出力制御(IOCTL)を介して afd.sys を呼び出す多くの参照バイナリがあります。また、どの呼び出しがどのインターフェースに関連しているかがわかり、ユーザーモードのアプリケーション呼び出しとカーネルモジュールのロジックのアクティブ化を結びつけることができます。これは、後にドライバーへの直接呼び出しを実行し、ドライバーのふるまいのデバッグを行うために役立ちます。
ロジックの詳細
この脆弱性は、UAF シナリオにつながる典型的な競合状態です。これは、AfdSocketTransfer*、AfdGetInformation、AfdBind、AfdConnect などの複数のディスパッチルーティンに影響します。
この核心的な問題は、ユーザーモードのアプリケーションが特定の IOCTL リクエストを発行し、それと同時に別のスレッドでソケットを閉じた場合に発生します。パッチが適用されていないバージョンでは、ドライバーは Endpoint、File Object、または Device Object へのポインターをフェッチし、それらを使用する際に、同時の閉じる操作によって基盤となるメモリが解放されないようにしていませんでした。これにより、カーネルが無効なメモリで動作するウィンドウが作成され、ローカルの攻撃者がカーネルメモリを破壊したり、権限を昇格させたりすることが可能になりました。
バインドされたソケット(Listen)のハンドルを使用して特定の情報クラスに対して afd!AfdGetInformation 関数を呼び出すプロセスでは、ソケットタイプやプロトコル層など、必要な条件を確認する必要があります。次に、コールフローをたどると、基盤となる関数に、呼び出し元が使用できるさまざまな操作のスイッチケースがあることがわかります。
脆弱なコードブロックは、AFD_MAX_PATH_SEND_SIZE ケース内に存在します(図 3)。つまり、脆弱なパスにヒットすると、呼び出し元がインターフェースを呼び出すときに正しい値を提供し、ソケットが接続状態になる必要があります。
class AFD_INFORMATION_CLASS(IntEnum):
AFD_INLINE_MODE = 1 # s: BOOLEAN
AFD_NONBLOCKING_MODE = 2 # s: BOOLEAN
AFD_MAX_SEND_SIZE = 3 # q: ULONG
AFD_SENDS_PENDING = 4 # q: ULONG
AFD_MAX_PATH_SEND_SIZE = 5 # q: ULONG
AFD_RECEIVE_WINDOW_SIZE = 6 # q; s: ULONG
AFD_SEND_WINDOW_SIZE = 7 # q; s: ULONG
AFD_CONNECT_TIME = 8 # q: ULONG (seconds)
AFD_CIRCULAR_QUEUEING = 9 # s: BOOLEAN
AFD_GROUP_ID_AND_TYPE = 10 # q: AFD_GROUP_INFO
AFD_REPORT_PORT_UNREACHABLE = 11 # s: BOOLEAN
AFD_REPORT_NETWORK_UNREACHABLE = 12 # s: BOOLEAN
AFD_DELIVERY_STATUS = 14 # q: SIO_DELIVERY_STATUS
AFD_CANCEL_TL = 15 # s: void
図 4 では、脆弱なコードの逆コンパイルバージョン(前)とパッチ適用されたコード(後)を比較しています。
競合状態
afd.sys ドライバーはエンドポイントのライフサイクルを維持します。また、Endpoint オブジェクトへは複数のスレッドから同時にアクセスできます。図 5 では、m_Endpoint->State はソケットの状態を表しています。
ソケットを有効な状態に保つために、カーネルモジュールは細心の注意を払ってソケットを扱う必要があります。このケースでは、別のスレッドを介して状態を変更できるウィンドウがあり、最終的に unbind コントールコマンドを使用してエンドポイントを完全に解放できます。
ローカルの攻撃者は、次の 2 つのスレッドの間に「競合」を生み出すことでこれを悪用できます。
スレッド A:脆弱な IOCTL を繰り返し送信する(例:IOCTL_AFD_GET_INFORMATION)
スレッド B:ソケットハンドルのバインドとバインド解除を繰り返す
スレッド A がポインターをフェッチした後、スレッド A がポインターを使用する前にスレッド B が競合状態に勝利した場合、スレッド A は解放されたメモリを逆参照します。
パーティをクラッシュさせる
PatchDiff-AI レポートやその他のリソースを使用すると、afd!AfdGetInformation 関数の使用方法を理解し、競合状態に勝利するための正しい引数によってその関数を呼び出すことができます(図 6)。
図 6:脆弱性をトリガーする概念実証コード
図 7 では、PageFault 例外が発生するまで AfdGetInformation を呼び出した場合のクラッシュの呼び出しスタックを確認できます。
攻撃ベクトル
これは、ローカルシステムにのみ影響するローカル権限昇格のバグです。攻撃者は低権限のローカルプロセスから任意のコードを実行し、競合状態を悪用して、より高い権限を取得できます。
PatchDiff-AI は攻撃手法を生み出すことを目的としたツールではありませんが、攻撃の疑いのあるプロシージャーを理解するのに役立ちます。
初期設定:攻撃者は NtCreateFile() を使用して有効な AfdSocket を開きます。
グルーミング/スプレー:厳密にはクラッシュに必要ではありませんが、EoP を確実に悪用するためには、多くの場合、解放された AFD_ENDPOINT を攻撃者が制御する偽の構造に置き換えるヒープスプレーが必要です。
トリガー:攻撃者は 2 つのスレッドを生成します。スレッド 1 は、脆弱な IOCTL(IOCTL_AFD_GET_INFORMATION など)で NtDeviceIoControlFile を繰り返します。スレッド 2 は、連続する IOCTL_AFD_BIND と IOCTL_AFD_UNBIND を繰り返します。
実行:競合状態に勝利すると、カーネルが攻撃者の偽のオブジェクトに対して呼び出し(IoGetRelatedDeviceObject など)を実行し、カーネルのメモリ操作が発生します。
システムのセキュリティを確保する方法
パッチ適用:唯一の効果的な保護は、関連する Windows セキュリティ更新プログラムをインストールすることです。このパッチは、バインド解除バリアを厳格に実行することによって afd.sys を強化します。
緩和:SIGMA または YARA ルールセットを使用して、攻撃試行である可能性のある AFD とのインタラクションを特定することで、脅威を軽減できる可能性があります。ほとんどの場合、IOCTL から afd ドライバーへの呼び出しを開始するプロセスを突き止め、繰り返し呼び出しを使用してカーネル・プール・メモリのスプレーを試みれば十分です(図 8)。
検知:AFD エンドポイント(ソケット)は最終的に Windows I/O サブシステムを介してファイルハンドルとして公開されるため、IRP コールを傍受し、特に切断されたエンドポイントの疑わしいアクティビティを監視できます。
import "pe"
rule CVE_2025_60719 {
meta:
description = "Detects exploits for CVE-2025-60719 targeting afd.sys"
author = "Maor Dahan"
date = "2025-12-01"
reference = "https://github.com/akamai/CVE-2025-60719-AFD.SYS"
strings:
// Core Indicators - The specific device name is strong indicator
$str_device = "\\Device\\Afd\\Endpoint" ascii wide
$str_device_double = "\\\\Device\\\\Afd\\\\Endpoint" ascii
// Specific IOCTL constants used in the exploit
// 0x12003 = IOCTL_AFD_BIND
$ioctl_str_bind = "0x12003" ascii
$ioctl_hex_bind = { 03 20 01 00 }
// 0x12113 = IOCTL_AFD_UNBIND
$ioctl_str_unbind = "0x12113" ascii
$ioctl_hex_unbind = { 13 21 01 00 }
// 0x1207B = IOCTL_AFD_GET_INFORMATION
$ioctl_str_info = "0x1207B" ascii
$ioctl_hex_info = { 7B 20 01 00 }
condition:
($str_device or $str_device_double) and
(
(
pe.is_pe and
pe.imports("ntdll.dll", "NtDeviceIoControlFile") and
all of ($ioctl_hex_*)
)
or
(
not pe.is_pe and
(
(
all of ($ioctl_str_*) or
3 of ($ioctl_*)
)
)
)
)
}
まとめ
PatchDiff-AI を使用すると、バイナリ変更とセキュリティロジックの相関を自動化し、無関係なコード変更のノイズに惑わされることなく根本原因を迅速に特定できます。これにより、セキュリティチームは迅速に行動して、ワンデイ攻撃を防止できます。
CVE-2025-60719 のケーススタディは、カーネルドライバーのパッチ管理の複雑さと、PatchDiff-AI ツールを使用した分析によってどのようにさまざまな目的のために知見に富んだ詳細な情報が得られるかを示しています。
タグ