flawopen.com/Incidents/windows-update-stack-symlink-eop-september-2026
CVE-2026-81963 : lien défectueux Windows Update
CVE-2026-81963 est une faille exploitée de résolution de liens dans Windows Update. Versions touchées, correctif et ouverture sûre des fichiers.[1], [2]
Un gardien de nuit muni d'un passe-partout livre des colis à « la réserve au bout du couloir » en suivant les flèches peintes sur les murs, sans vérifier où il arrive. Les locataires ont le droit de déplacer ces flèches. L'un d'eux tourne la flèche de la réserve vers le bureau du directeur, et le gardien, dont la clé ouvre toutes les portes, entre et pose le colis sur le bureau du directeur. Le locataire n'aurait jamais pu ouvrir cette porte ; la clé du gardien l'a fait pour lui. La correction consiste à ce que le gardien lise le numéro de la porte qu'il a réellement ouverte et cesse de suivre des flèches que les locataires peuvent déplacer.[5], [9]
Concepts Clés et Termes
Windows Update Stack- Les composants de Windows qui recherchent, téléchargent, préparent et installent les mises à jour. Ils s'exécutent en SYSTEM, car installer des mises à jour implique d'écrire dans des zones protégées du système.[1]
SYSTEM (NT AUTHORITY\SYSTEM)- Le compte local sous lequel s'exécutent les services Windows. Il a plus de droits qu'un administrateur sur la machine locale ; presque aucune opération sur fichier ne lui est refusée.[1]
Jonction / lien symbolique (reparse point)- Objets NTFS qui font pointer un chemin vers un autre. Un utilisateur standard peut créer une jonction dans un dossier qu'il contrôle et rediriger ce nom vers un répertoire où il ne peut pas écrire.[9]
Suivi de liens (CWE-59)- Un programme ouvre, écrit, déplace ou supprime un fichier par son nom sans vérifier que ce nom se résout là où il l'attend ; un lien placé par quelqu'un d'autre détourne alors l'opération.[5], [2]
FILE_FLAG_OPEN_REPARSE_POINT- Un indicateur de CreateFileW qui ouvre le dernier composant du chemin lui-même s’il s’agit d’un point de réanalyse, au lieu de suivre ce dernier lien. À lui seul, il n’empêche pas le traitement des points de réanalyse dans les composants précédents.[6]
TOCTOU (CWE-367)- Time-of-check to time-of-use : le système de fichiers change entre une vérification et l'opération qui en dépend. Vérifier une chaîne de chemin puis l'ouvrir par son nom laisse cette fenêtre ouverte.[12]
CWE-284 (contrôle d’accès inadéquat)- Microsoft attribue les
CWE-59etCWE-284à cette CVE. LaCWE-59désigne le défaut précis de résolution des liens. LaCWE-284est une Pillar CWE générale que MITRE déconseille explicitement pour le mappage de vulnérabilités réelles. Il faut la lire comme la classification plus large de Microsoft pour ce même problème signalé, et non comme la preuve d’un second bogue.[2], [11], [5]
Correspondances de référentiels
- Référence CWE pour la faiblesse décrite dans ce guide : CWE-59 CWE-284
- CISA KEV — ajouté le 2026-09-08 — CVE-2026-81963
Chronologie de l'Incident
Microsoft réserve CVE-2026-81963.[2]
Patch Tuesday de septembre : Microsoft publie le correctif et marque la faille « Exploitation Detected » et non divulguée publiquement.[1]
La CISA ajoute CVE-2026-81963 au catalogue Known Exploited Vulnerabilities, avec une échéance de correction au 22 septembre 2026 pour les agences fédérales américaines.[4]
Microsoft publie une révision de l'avis.[1]
Déroulement de l'Attaque Étape par Étape
Un service SYSTEM travaille dans un chemin modifiable par les utilisateurs
Les composants de l'Update Stack s'exécutent en SYSTEM et manipulent des fichiers dans des répertoires de préparation et de travail. Si un utilisateur standard peut créer, supprimer ou renommer des entrées n'importe où sur ce chemin, c'est lui qui décide où il se résout. Microsoft n'a pas précisé quel chemin était concerné ici.[1]
Le service suit le lien
Windows résout normalement les points de réanalyse lors de l’ouverture d’un chemin. FILE_FLAG_OPEN_REPARSE_POINT concerne le composant final ; les composants précédents peuvent encore être résolus. Si le service écrit ensuite via un chemin non validé, le contrôle d’accès utilise son jeton SYSTEM. Validez le handle du répertoire et créez le fichier enfant relativement à ce handle.[6], [8]
Code Source : Vulnérable vs Sécurisé
Microsoft n’a publié ni la fonction touchée ni son correctif. Cet exemple défensif n’est pas le code de Microsoft. Vérifier uniquement le propriétaire ne suffit pas : le propriétaire d’un objet ne prouve pas que sa DACL refuse l’écriture aux utilisateurs standard. Ce modèle suppose que l’installateur crée le chemin fixe de staging et tous ses répertoires parents avec une DACL explicite autorisant l’écriture uniquement à SYSTEM et Administrators. La fonction ne lit ni ne valide la DACL ; les autorisations définies par l’installateur sont un prérequis de déploiement. Il valide le handle du répertoire ouvert, puis crée un nom de fichier unique relatif à ce handle avec NtCreateFile et FILE_CREATE ; il ne rouvre jamais un chemin concaténé. Testez la DACL et le comportement du système de fichiers dans les déploiements pris en charge. Installez la mise à jour Microsoft pour corriger CVE-2026-81963.[5], [6], [7], [8], [9], [10]
Extrait source: Exemple illustratif de gestion des chemins Windows ; ce n’est pas du code Microsoft
/* Exemple illustratif, pas le code source de Microsoft : la fonction concernée n’a pas
* été publiée. Un service SYSTEM écrit dans un répertoire de staging modifiable par les
* utilisateurs standard.
*/
BOOL WriteStagedFile(LPCWSTR stagingDir, LPCWSTR name,
const BYTE *data, DWORD size)
{
WCHAR path[MAX_PATH];
if (FAILED(StringCchPrintfW(path, MAX_PATH, L"%s\\%s", stagingDir, name)))
return FALSE;
/* CWE-59 : CreateFileW résout les jonctions et liens symboliques dans chaque
* composant du chemin ; le contrôle utilise le jeton SYSTEM. Si un utilisateur
* remplace stagingDir par une jonction, l’écriture suit sa cible.
*/
HANDLE h = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if (h == INVALID_HANDLE_VALUE)
return FALSE;
DWORD written = 0;
BOOL ok = WriteFile(h, data, size, &written, NULL) && written == size;
CloseHandle(h);
return ok;
}/* Modèle de défense illustratif, ni code source ni correctif Microsoft. Le programme
* d’installation doit créer ce chemin et chaque répertoire parent avec une DACL
* explicite autorisant l’écriture uniquement à SYSTEM et Administrators.
*/
#include <windows.h>
#include <winternl.h>
static const WCHAR STAGING_DIR[] =
L"C:\\ProgramData\\Vendor\\Update\\Staging";
BOOL WriteStagedFile(LPCWSTR name, const BYTE *data, DWORD size)
{
if (name == NULL || data == NULL || name[0] == L'\0' ||
wcspbrk(name, L"\\/:") != NULL || wcscmp(name, L".") == 0 ||
wcscmp(name, L"..") == 0)
return FALSE;
/* Verrouiller l’objet répertoire ; l’absence de FILE_SHARE_DELETE empêche son
* renommage.
*/
HANDLE dir = CreateFileW(STAGING_DIR,
FILE_LIST_DIRECTORY | FILE_TRAVERSE | FILE_READ_ATTRIBUTES,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS |
FILE_FLAG_OPEN_REPARSE_POINT,
NULL);
if (dir == INVALID_HANDLE_VALUE)
return FALSE;
FILE_ATTRIBUTE_TAG_INFO tag;
WCHAR actual[MAX_PATH];
BOOL ok = FALSE;
DWORD n;
if (!GetFileInformationByHandleEx(dir, FileAttributeTagInfo,
&tag, sizeof tag) ||
(tag.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
goto done;
n = GetFinalPathNameByHandleW(dir, actual, MAX_PATH,
FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
if (n == 0 || n >= MAX_PATH ||
_wcsicmp(actual, L"\\\\?\\C:\\ProgramData\\Vendor\\Update\\Staging") != 0)
goto done;
/* Ouvrir le nouvel enfant relativement à ce handle, sans jamais reconstruire le
* chemin.
*/
size_t nameChars = wcslen(name);
if (nameChars == 0 || nameChars > 255)
goto done;
USHORT nameBytes = (USHORT)(nameChars * sizeof(WCHAR));
UNICODE_STRING relativeName = { nameBytes, nameBytes, (PWSTR)name };
OBJECT_ATTRIBUTES oa = {0};
oa.Length = sizeof oa;
oa.RootDirectory = dir;
oa.ObjectName = &relativeName;
oa.Attributes = OBJ_CASE_INSENSITIVE;
IO_STATUS_BLOCK iosb = {0};
HANDLE file = INVALID_HANDLE_VALUE;
NTSTATUS status = NtCreateFile(
&file, FILE_WRITE_DATA | SYNCHRONIZE, &oa, &iosb, NULL,
FILE_ATTRIBUTE_NORMAL, 0, FILE_CREATE,
FILE_NON_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT, NULL, 0);
if (!NT_SUCCESS(status))
goto done; /* FILE_CREATE échoue si une entrée existe déjà. */
DWORD written = 0;
ok = WriteFile(file, data, size, &written, NULL) && written == size;
CloseHandle(file);
done:
CloseHandle(dir);
return ok;
}Liste de Contrôle de Sécurité pour l'Ingénierie
- ✓Installez la mise à jour cumulative de septembre 2026 : KB5124008 (Windows 11 24H2 et 25H2), KB5122880 (23H2), KB5124012 (26H1) ou KB5122871 (Server 2025). Les builds corrigées sont 10.0.26100.9445, 10.0.26200.9445, 10.0.22631.7582, 10.0.28000.2954 et, pour Server 2025, 10.0.26100.33438.[1]
- ✓Dans chaque service exécuté en SYSTEM ou en administrateur, recensez tous les appels à CreateFileW, DeleteFileW, MoveFileExW, CopyFileW et SetFileSecurityW dont le chemin se trouve sous %ProgramData%, %TEMP%, C:\Users ou un autre emplacement accessible en écriture aux utilisateurs, et exigez une revue de chacun.
- ✓Ouvrez les répertoires avec FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, refusez ceux qui portent FILE_ATTRIBUTE_REPARSE_POINT et gardez le handle ouvert sans FILE_SHARE_DELETE pendant que vous y travaillez.[6], [9]
- ✓Vérifiez la cible avec GetFinalPathNameByHandleW sur le handle ouvert avant d'écrire ; ne vous fiez jamais à la chaîne de chemin que vous avez construite.[7]
- ✓Utilisez CREATE_NEW (ou FILE_CREATE avec NtCreateFile) plutôt que CREATE_ALWAYS dans les répertoires partagés : un fichier ou lien existant fera échouer l’opération au lieu d’être écrasé.[8]
- ✓Créez les répertoires de travail du service avec une DACL explicite n'accordant l'écriture qu'à SYSTEM et Administrators, et faites échouer les tests de l'installeur si icacls montre un droit d'écriture pour Users ou Authenticated Users.[10]
- ✓Lorsqu'un service effectue des opérations sur fichiers pour le compte d'un appelant, empruntez l'identité de cet appelant (RpcImpersonateClient, ImpersonateNamedPipeClient) afin que l'accès soit vérifié avec son jeton et non avec celui de SYSTEM.
- ✓Déclenchez une alerte lorsque des processus d'utilisateur standard créent des jonctions ou des points de montage sous %ProgramData% ou %windir% ; c'est rare en usage normal et c'est ainsi que commencent les attaques par suivi de liens.
- ✓Créez le fichier enfant relativement au handle du répertoire validé avec
NtCreateFileetFILE_CREATE; ne rouvrez jamaisstagingDir\nameà partir d’un chemin concaténé après avoir vérifié le répertoire.[8]
Sources
- Microsoft Security Response Center — CVE-2026-81963, vulnérabilité d'élévation de privilèges dans la Windows Update Stack
- CVE-2026-81963 — fiche CVE
- NVD — CVE-2026-81963
- CISA — catalogue Known Exploited Vulnerabilities
- MITRE CWE-59 : résolution incorrecte de liens avant l'accès à un fichier
- Microsoft Learn — CreateFileW
- Microsoft Learn — GetFinalPathNameByHandleW
- Microsoft Learn — NtCreateFile (directory-relative names)
- Microsoft Learn — Reparse points and file operations
- Microsoft Learn — GetSecurityInfo (owner and DACL)
- MITRE CWE-284: Improper Access Control
- MITRE CWE-367: Time-of-check Time-of-use (TOCTOU) Race Condition