flawopen.com/Incidents/windows-update-stack-symlink-eop-september-2026
CVE-2026-81963: link falho no Windows Update
CVE-2026-81963 é uma falha explorada na resolução de links do Windows Update. Veja as versões afetadas, a correção e o tratamento seguro de arquivos.[1], [2]
Um porteiro noturno com chave-mestra entrega encomendas no "depósito no fim do corredor", seguindo as setas pintadas nas paredes sem conferir onde vai parar. Os inquilinos podem mudar essas setas de lugar. Um deles vira a seta do depósito para apontar para a sala do gerente, e o porteiro, cuja chave abre todas as portas, entra e deixa a encomenda na mesa do gerente. O inquilino jamais conseguiria abrir aquela porta; a chave do porteiro fez isso por ele. A correção é o porteiro ler o número da porta que realmente abriu e deixar de seguir setas que os inquilinos podem mover.[5], [9]
Conceitos Centrais e Termos
Windows Update Stack- Os componentes do Windows que procuram, baixam, preparam e instalam atualizações. Rodam como SYSTEM porque instalar atualizações exige gravar em áreas protegidas do sistema operacional.[1]
SYSTEM (NT AUTHORITY\SYSTEM)- A conta local sob a qual os serviços do Windows rodam. Ela tem mais direitos que um administrador na máquina local, então quase nenhuma operação de arquivo feita por ela é recusada.[1]
Junction / link simbólico (reparse point)- Objetos do NTFS que fazem um caminho apontar para outro. Um usuário padrão pode criar uma junction numa pasta que controla, redirecionando o nome dessa pasta para um diretório em que não pode gravar.[9]
Seguimento de links (CWE-59)- Um programa abre, grava, move ou apaga um arquivo pelo nome sem verificar se esse nome resolve para onde espera, de modo que um link plantado por outra pessoa desvia a operação.[5], [2]
FILE_FLAG_OPEN_REPARSE_POINT- Uma flag do CreateFileW que abre o componente final do caminho como ponto de nova análise, em vez de seguir esse link final. Ela, sozinha, não impede a resolução de pontos de nova análise nos componentes anteriores.[6]
TOCTOU (CWE-367)- Time-of-check to time-of-use: o sistema de arquivos muda entre uma verificação e a operação que depende dela. Verificar uma string de caminho e depois abri-la pelo nome deixa essa janela aberta.[12]
CWE-284 (controle de acesso inadequado)- A Microsoft atribui
CWE-59eCWE-284a esta CVE.CWE-59identifica a falha específica de resolução de links.CWE-284é uma Pillar CWE ampla que a MITRE desaconselha explicitamente para mapear vulnerabilidades do mundo real. Considere-a uma classificação mais ampla da Microsoft para o mesmo problema reportado, não evidência de um segundo bug.[2], [11], [5]
Mapeamentos de frameworks
- Referência CWE para a fraqueza descrita neste guia: CWE-59 CWE-284
- CISA KEV — adicionado em 2026-09-08 — CVE-2026-81963
Linha do Tempo do Incidente
A Microsoft reserva a CVE-2026-81963.[2]
Patch Tuesday de setembro: a Microsoft publica a correção e marca a falha como "Exploitation Detected" e não divulgada publicamente.[1]
A CISA adiciona a CVE-2026-81963 ao catálogo Known Exploited Vulnerabilities, com prazo de correção em 22 de setembro de 2026 para órgãos federais dos EUA.[4]
A Microsoft publica uma revisão do aviso.[1]
Fluxo de Ataque Passo a Paso
Um serviço SYSTEM trabalha num caminho que usuários podem alterar
Componentes da Update Stack rodam como SYSTEM e manipulam arquivos em diretórios de preparação e de trabalho. Se um usuário padrão pode criar, apagar ou renomear entradas em qualquer ponto desse caminho, é ele quem decide para onde o caminho resolve. A Microsoft não informou qual caminho foi afetado neste caso.[1]
O serviço segue o link
O Windows normalmente resolve pontos de nova análise ao abrir um caminho. FILE_FLAG_OPEN_REPARSE_POINT controla o componente final; componentes anteriores ainda podem ser resolvidos. Se o serviço gravar por um caminho não validado, a verificação de acesso usa o token SYSTEM. Valide o identificador do diretório e crie o arquivo filho relativo a esse identificador.[6], [8]
Código-Fonte: Vulnerável vs. Seguro
A Microsoft não publicou a função afetada nem o patch. Este exemplo defensivo não é código da Microsoft. Verificar apenas o proprietário é insuficiente: o proprietário de um objeto não prova que a DACL negue gravação a usuários comuns. O padrão pressupõe que o instalador crie o caminho fixo de preparação e todos os diretórios pais com uma DACL explícita que permita gravação somente a SYSTEM e Administrators. A função não lê nem valida a DACL; as permissões configuradas pelo instalador são um pré-requisito de implantação. Ele valida o identificador do diretório aberto e cria um único nome de arquivo relativo a esse identificador com NtCreateFile e FILE_CREATE; não reabre um caminho concatenado. Teste a DACL e o comportamento do sistema de arquivos nas implantações suportadas. Instale a atualização da Microsoft para corrigir a CVE-2026-81963.[5], [6], [7], [8], [9], [10]
Trecho de origem: Exemplo ilustrativo de tratamento de caminhos no Windows; não é código da Microsoft
/* Exemplo ilustrativo, não é código-fonte da Microsoft: a função afetada não foi
* publicada. Um serviço SYSTEM grava em uma pasta de staging que usuários comuns podem
* modificar.
*/
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 resolve junctions e links simbólicos em cada componente do
* caminho; a verificação usa o token SYSTEM. Se um usuário trocar stagingDir por
* uma junction, a gravação irá para o destino dela.
*/
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;
}/* Padrão defensivo ilustrativo, não é código-fonte nem patch da Microsoft. O instalador
* deve criar este caminho e todos os diretórios pais com DACL explícita que permita
* gravação apenas a SYSTEM e 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;
/* Fixe o objeto do diretório; sem FILE_SHARE_DELETE, a renomeação é bloqueada. */
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;
/* Abra o novo item relativo a este handle; nunca reconstrua o caminho. */
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 falha se a entrada já existir. */
DWORD written = 0;
ok = WriteFile(file, data, size, &written, NULL) && written == size;
CloseHandle(file);
done:
CloseHandle(dir);
return ok;
}Lista de Verificação de Segurança para Engenharia
- ✓Instale a atualização cumulativa de setembro de 2026: KB5124008 (Windows 11 24H2 e 25H2), KB5122880 (23H2), KB5124012 (26H1) ou KB5122871 (Server 2025). As builds corrigidas são 10.0.26100.9445, 10.0.26200.9445, 10.0.22631.7582, 10.0.28000.2954 e, no Server 2025, 10.0.26100.33438.[1]
- ✓Em todo serviço que roda como SYSTEM ou administrador, liste cada chamada a CreateFileW, DeleteFileW, MoveFileExW, CopyFileW e SetFileSecurityW cujo caminho esteja em %ProgramData%, %TEMP%, C:\Users ou outro local gravável por usuários, e exija revisão de cada uma.
- ✓Abra diretórios com FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, rejeite os que tiverem FILE_ATTRIBUTE_REPARSE_POINT e mantenha o handle aberto sem FILE_SHARE_DELETE enquanto trabalha dentro dele.[6], [9]
- ✓Confirme o destino com GetFinalPathNameByHandleW no handle aberto antes de gravar; nunca confie na string de caminho que você montou.[7]
- ✓Use CREATE_NEW (ou FILE_CREATE do NtCreateFile) em vez de CREATE_ALWAYS em diretórios compartilhados, para que um arquivo ou link existente faça a operação falhar em vez de ser sobrescrito.[8]
- ✓Crie os diretórios de trabalho do serviço com uma DACL explícita que dê escrita apenas a SYSTEM e Administrators, e reprove os testes do instalador se o icacls mostrar escrita para Users ou Authenticated Users.[10]
- ✓Quando um serviço faz operações de arquivo em nome de um chamador, personifique o chamador (RpcImpersonateClient, ImpersonateNamedPipeClient) para que o acesso seja verificado contra o token dele, e não o de SYSTEM.
- ✓Gere alertas quando processos de usuário padrão criarem junctions ou mount points sob %ProgramData% ou %windir%; isso é raro no uso normal e é assim que ataques de seguimento de links começam.
- ✓Crie o arquivo filho relativo ao identificador de diretório validado usando
NtCreateFileeFILE_CREATE; nunca reabrastagingDir\namepor um caminho concatenado depois de verificar o diretório.[8]
Fontes
- Microsoft Security Response Center — CVE-2026-81963, vulnerabilidade de elevação de privilégio na Windows Update Stack
- CVE-2026-81963 — registro CVE
- NVD — CVE-2026-81963
- CISA — catálogo Known Exploited Vulnerabilities
- MITRE CWE-59: resolução imprópria de links antes do acesso a arquivos
- 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