flawopen.com/Инциденты/Эскалация привилегий через Symlink в Windows Update
Представьте общедоступный почтовый ящик в холле офиса. Стажер наклеивает записку: 'Всю входящую корреспонденцию перенаправлять в личный сейф генерального директора'. Ночью охранник с универсальным ключом (служба Windows Update с правами SYSTEM) слепо выполняет указание, открывает сейф и кладет туда посылку стажера, отдавая ему полный контроль над зданием.
On September 8, 2026 (September 2026 Patch Tuesday), Microsoft released patches for an actively exploited zero-day vulnerability tracked as CVE-2026-81963. The vulnerability was discovered in the wild being utilized by sophisticated threat actors to elevate from low-privileged user accounts (and sandboxed AppContainers) to full NT AUTHORITY\SYSTEM control on Windows 11 and Windows Server 2025.
Classified under CWE-59 (Improper Link Resolution Before File Access), the flaw resided in the Windows Update Stack—specifically the Update Orchestrator worker (MoUsoCoreWorker.exe). The service relied on a staging directory inside C:\ProgramData\USOPrivate\UpdateStore\ to cache download manifests, metadata, and temporary update CAB files.
Because standard unprivileged users have permission to create folders and manipulate files within ProgramData, attackers replaced the staging directory with an NTFS directory junction point pointing to protected operating system directories (such as C:\Windows\System32). When the Update Orchestrator initiated a background scan or update check, it executed file creation and DACL permission resets as SYSTEM without verifying whether the directory had been redirected, granting attackers full control over critical system binaries.
The Windows Update Stack used C:\ProgramData\USOPrivate\UpdateStore as its scratchpad. Under default Windows NTFS security descriptors, the C:\ProgramData root allows standard authenticated users to create subdirectories and files, creating a shared boundary between unprivileged users and a privileged system service.
When MoUsoCoreWorker.exe accessed files and created folders in its staging directory, it invoked standard Win32 APIs (CreateFileW, CreateDirectoryW) without passing FILE_FLAG_OPEN_REPARSE_POINT. Windows transparently resolved the NTFS junction, redirecting the high-privilege write operations to the attacker's chosen target.
The update worker failed to verify the filesystem security descriptor and owner SID of the staging path. If a path was owned by standard unprivileged users (e.g., BUILTIN\Users), the service should have rejected it immediately rather than trusting it for administrative operations.
// Conceptual flaw in Windows Update Stack worker
BOOL StageUpdateManifest(LPCWSTR manifestName, PBYTE data, DWORD size) {
WCHAR targetPath[MAX_PATH];
// Path under user-writable ProgramData!
StringCchPrintfW(targetPath, MAX_PATH, L"C:\\ProgramData\\USOPrivate\\UpdateStore\\%s", manifestName);
// VULNERABILITY (CWE-59):
// CreateFileW does NOT specify FILE_FLAG_OPEN_REPARSE_POINT!
// If 'UpdateStore' is an NTFS junction to C:\Windows\System32,
// this creates/overwrites files in System32 as NT AUTHORITY\SYSTEM!
HANDLE hFile = CreateFileW(
targetPath,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, // Missing FILE_FLAG_OPEN_REPARSE_POINT
NULL
);
WriteFile(hFile, data, size, &written, NULL);
CloseHandle(hFile);
return TRUE;
}
// Fixed Windows Update Stack implementation
BOOL StageUpdateManifest(LPCWSTR manifestName, PBYTE data, DWORD size) {
WCHAR targetPath[MAX_PATH];
StringCchPrintfW(targetPath, MAX_PATH, L"C:\\ProgramData\\USOPrivate\\UpdateStore\\%s", manifestName);
// FIX 1: Open directory with FILE_FLAG_OPEN_REPARSE_POINT to detect junctions
HANDLE hDir = CreateFileW(
L"C:\\ProgramData\\USOPrivate\\UpdateStore",
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
NULL
);
// Abort if target directory is a reparse point / junction
BY_HANDLE_FILE_INFORMATION fileInfo;
GetFileInformationByHandle(hDir, &fileInfo);
if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
CloseHandle(hDir);
return FALSE; // Access Denied: Junction detected!
}
// FIX 2: Validate owner SID must be SYSTEM or Administrators
if (!IsOwnerSystemOrAdmin(hDir)) {
CloseHandle(hDir);
return FALSE;
}
// Safe write strictly constrained to verified non-reparse path
return SafeWriteVerifiedFile(targetPath, data, size);
}
# Sysmon Event ID 11: Detect junction point or symlink creation in USOPrivate
EventID=11 AND TargetFilename="*\ProgramData\USOPrivate\*"
# PowerShell: Audit reparse points under ProgramData
Get-ChildItem -Path "C:\ProgramData" -Recurse -Force -ErrorAction SilentlyContinue | Where-Object { $_.LinkType -ne $null }
# Sysmon Event ID 1: Detect unprivileged usoclient triggers
EventID=1 AND CommandLine="*usoclient*StartInteractiveScan*"
SYSTEM that opens files in shared or user-writable paths must inspect reparse tags before file writes.GetSecurityInfo that the folder owner is NT AUTHORITY\SYSTEM or BUILTIN\Administrators.ImpersonateLoggedOnUser() so write permissions are evaluated against the caller's low-privilege token rather than the service's SYSTEM token.