Synthèse
Les chercheurs d'Akamai ont créé une nouvelle fonctionnalité d'IA qui effectue une analyse instantanée des causes premières. L'outil, un système multi‑agents supervisé nommé PatchDiff‑AI, est utilisé dans cet article pour étudier en profondeur la vulnérabilité CVE‑2025‑60719, qui affecte presque toutes les versions de Windows.
La vulnérabilité : une vulnérabilité « use-after-free » (UAF) dans le pilote de fonction auxiliaire de Windows (afd.sys) pour Winsock, provoquée par une condition de concurrence (race condition)
L'impact : élévation locale des privilèges ; un attaquant disposant de privilèges faibles peut manipuler la mémoire du noyau et obtenir des privilèges système
La cause profonde : le pilote n'a pas empêché la désactivation/libération du point de terminaison d'un socket alors que d'autres opérations (comme Transfer, GetInformation ou Connect) continuaient à déréférencer les objets qui y étaient associés
Le correctif : Microsoft a ajouté un mécanisme de barrière de synchronisation (AfdPreventUnbind/AfdReallowUnbind) pour verrouiller explicitement l'état du point de terminaison pendant les opérations critiques
Poursuivez votre lecture pour découvrir comment PatchDiff-AI permet d'analyser rapidement la cause profonde d'une vulnérabilité critique de Patch Tuesday et aide les équipes de sécurité à détecter et à atténuer plus efficacement les vulnérabilités de type One Day.
La vulnérabilité
La CVE-2025-60719 reflète une faille importante dans la pile réseau du noyau Windows, plus précisément dans afd.sys, un composant essentiel de l'API Winsock. Lorsque l'exploitation est réussie, un processus disposant de privilèges faibles peut obtenir des privilèges système. Notre exploit échoue toutefois lorsqu'il est exécuté depuis un processus AppContainer, faute d'autorisations suffisantes.
Cette vulnérabilité affecte de nombreux produits Windows, y compris toutes les versions Windows suivantes :
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 : versions 1607, 1809, 21H2, 22H2
Autres versions obsolètes
Un éventail aussi large augmente considérablement la surface d'attaque.
Analyse des causes premières
PatchDiff-AI permet d'analyser rapidement le correctif de sécurité censé résoudre la vulnérabilité selon l'éditeur. Les résultats de l'outil indiquent que les modifications de code concernées impliquent les méthodes AfdSocketTransfer*, AfdGetInformation, AfdBind et AfdConnect.
Un examen plus approfondi révèle que la cause profonde de cette vulnérabilité réside dans la gestion du cycle de vie de la structure AFD Endpoint (nommée AFD_ENDPOINT) et dans l'absence d'atomicité (synchronisation des opérations simultanées) entre l'extraction d'un pointeur d'objet et son utilisation.
Analyse des modifications
L'outil PatchDiff-AI a mis en évidence un composant directement lié à la logique centrale de la vulnérabilité : le pilote de fonction auxiliaire (afd.sys), qui assure le support réseau de base de la couche de transport dans Windows. Il fournit l'interface Winsock, gère les sockets réseau et gère d'autres fonctionnalités liées aux E/S.
L'analyse de l'outil s'appuie sur la comparaison entre la version corrigée 10.0.26100.7171, disponible avec la mise à jour de sécurité KB5068861, et la version vulnérable 10.0.26100.6899, disponible avec la mise à jour de sécurité KB5066835.
Cinq fonctions ont été modifiées au total, toutes classées par l'outil comme étant liées à la sécurité.
L'analyse de la fonction AfdGetInformation montre un bloc de code désormais protégé par le blocage de l'opération unbind, ce qui empêche le socket d'être libéré (Figure 1). Ce changement faisant référence au cycle de vie des sockets et interférant avec leur état, nous pouvons raisonnablement supposer qu'il est lié à une vulnérabilité UAF.
Présentation rapide du pilote de fonction auxiliaire
Des articles complets sur le fonctionnement du pilote de fonction auxiliaire (afd.sys) et son utilisation. Pour résumer, il s'agit d'un composant Windows qui assure le service de l'API Winsock. Il permet aux processus disposant de privilèges faibles d'utiliser la pile réseau pour TCP/IP et d'autres protocoles de communication.
La Figure 2 présente de nombreux binaires de référence qui appellent afd.sys via des contrôles d'entrée/sortie (IOCTL). Cela montre quel appel est lié à quelle interface, afin de faire le lien entre les appels applicatifs en mode utilisateur et l'activation logique du module noyau. Nous pouvons ainsi appeler directement le pilote et en identifier les anomalies comportementales pour les corriger.
Compréhension de la logique
La vulnérabilité est une condition de concurrence classique qui conduit à un scénario UAF. Elle affecte plusieurs routines de dispatch, notamment AfdSocketTransfer*, AfdGetInformation, AfdBind et AfdConnect.
Le problème de fond se manifeste lorsqu'une application en mode utilisateur émet une requête IOCTL spécifique tout en fermant simultanément le socket dans un autre thread. Dans la version non corrigée, le pilote récupérait des pointeurs vers l'Endpoint, le File Object ou le Device Object, puis les utilisait sans s'assurer que la mémoire sous-jacente n'avait pas été libérée par l'opération de fermeture simultanée. Cela créait une fenêtre durant laquelle le noyau opérait sur de la mémoire non valide, permettant à un attaquant local de corrompre la mémoire du noyau ou d'obtenir des privilèges élevés.
Lorsqu'un processus appelle la fonction AfdGetInformation pour une classe d'information spécifique en utilisant un handle correspondant à un socket lié (listen), plusieurs conditions doivent être vérifiées, telles que le type de socket et sa couche protocolaire. Ensuite, si nous suivons le flux d'appels, nous pouvons constater que la fonction sous-jacente s'appuie sur un switch case pour déterminer l'opération demandée par l'appelant.
Le bloc de code vulnérable se trouve dans le cas AFD_MAX_PATH_SEND_SIZE (Figure 3). Autrement dit, pour atteindre le chemin vulnérable, l'appelant doit fournir les valeurs correctes lors de l'appel de l'interface et le socket doit être connecté.
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
Dans la Figure 4, vous trouverez une version décompilée du code vulnérable (avant) comparé au code corrigé (après).
La condition de concurrence
Le pilote afd.sys maintient le cycle de vie du point de terminaison, et l'objet Endpoint est accessible simultanément à partir de plusieurs threads. Dans la Figure 5, m_Endpoint->State représente l'état du socket.
Pour maintenir le socket dans un état valide, le module noyau doit faire preuve d'une extrême prudence. Dans ce cas, il existe une fenêtre au cours de laquelle l'état peut être modifié via un autre thread, jusqu'à libérer complètement le point de terminaison via la commande de contrôle unbind.
Un attaquant local peut exploiter cela en créant une « course » entre deux threads :
Thread A : envoie en boucle un IOCTL vulnérable (ex. : IOCTL_AFD_GET_INFORMATION)
Thread B : exécute en boucle des opérations de bind et unbind sur le handle du socket
Si le Thread B gagne la course après que le Thread A a récupéré le pointeur mais avant que le Thread A ne l'utilise, alors ce dernier va déréférencer une mémoire libérée.
Déclenchement du crash
À l'aide du rapport PatchDiff-AI et des autres ressources, nous pouvons comprendre comment utiliser la fonction afd!AfdGetInformation et l'appeler avec les bons arguments pour remporter la course (Figure 6).
Fig. 6 : Code de preuve de concept qui déclenche la vulnérabilité
La Figure 7 présente la pile d'appels du crash lorsque AfdGetInformation est appelée jusqu'à l'exception PageFault.
Vecteur d'attaque
Il s'agit d'une faille locale d'élévation de privilèges qui n'affecte que le système local. Un attaquant capable d'exécuter du code arbitraire à partir d'un processus local disposant de privilèges faibles peut exploiter la condition de concurrence et obtenir des privilèges plus élevés.
Bien que l'outil PatchDiff-AI ne soit pas conçu pour créer un exploit, il peut aider à comprendre la procédure d'exploitation présumée.
Initialisation : l'attaquant ouvre un AfdSocket valide via NtCreateFile().
Grooming (préparation)/spraying : bien que non strictement nécessaire au crash, une exploitation fiable pour une élévation de privilèges implique souvent un heap spraying afin de remplacer l'AFD_ENDPOINT libéré par une structure factice contrôlée par l'attaquant.
Déclenchement : l'attaquant génère deux threads. Le Tread 1 boucle sur NtDeviceIoControlFile avec l'IOCTL vulnérable (ex. : IOCTL_AFD_GET_INFORMATION). Thread 2 boucle sur IOCTL_AFD_BIND et IOCTL_AFD_UNBIND.
Exécution : Lorsque la course est gagnée, le noyau exécute un appel (comme IoGetRelatedDeviceObject) sur l'objet factice de l'attaquant, ce qui entraîne une manipulation de la mémoire noyau.
Comment sécuriser votre système
Appliquer le correctif : installer la mise à jour de sécurité Windows appropriée est la seule protection efficace. Le correctif renforce afd.sys en appliquant strictement la barrière unbind.
Atténuation : l'utilisation d'un ensemble de règles SIGMA ou YARA pour identifier l'interaction avec AFD pouvant indiquer une tentative d'exploitation peut réduire la menace. Dans la plupart des cas, tracer les processus qui initient les appels IOCTL vers le pilote afd et détecter les tentatives de spray de la mémoire du kernel pool via des appels répétés peut être suffisant (Figure 8).
Détection : comme le point de terminaison AFD (socket) est exposé via le sous-système d'E/S Windows sous forme de handle de fichier, nous pouvons intercepter les appels IRP et surveiller les activités suspectes, en particulier celles concernant les points de terminaison déconnectés.
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_*)
)
)
)
)
}
Réflexions finales
PatchDiff-AI permet d'automatiser la corrélation entre les modifications binaires et la logique de sécurité, afin d'identifier rapidement la cause profonde sans vous laisser distraire par les modifications de code non pertinentes. Les équipes de sécurité peuvent ainsi agir rapidement pour prévenir les exploits One Day.
L'étude consacrée à la CVE-2025-60719 rappelle combien la gestion des correctifs au niveau des pilotes du noyau est complexe, et illustre comment l'analyse de PatchDiff‑AI apporte un éclairage précieux pour de nombreux scénarios.
Balises