FlawOpen

flawopen.com/Incidents/windows-update-stack-symlink-eop-september-2026

● Microsoft · CVE-2026-81963 · September 2026 · CVSS 7.8 · Alta
Pesquisa · FlawOpen

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]

💡 Explicação em Linguagem Simples (ELI5)

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-59 e CWE-284 a esta CVE. CWE-59 identifica 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

Linha do Tempo do Incidente

2026-08-27

A Microsoft reserva a CVE-2026-81963.[2]

2026-09-08

Patch Tuesday de setembro: a Microsoft publica a correção e marca a falha como "Exploitation Detected" e não divulgada publicamente.[1]

2026-09-08

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]

2026-09-15

A Microsoft publica uma revisão do aviso.[1]

Fluxo de Ataque Passo a Paso

Passo 1

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]

Passo 2

O caminho é redirecionado

Uma junction ou link simbólico faz o nome de um diretório resolver para outro lugar, como uma pasta protegida do sistema. Criar uma junction numa pasta que o usuário controla não exige direitos de administrador.[5], [9]

Passo 3

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]

Passo 4

Um local protegido é alterado

O serviço cria, sobrescreve, move ou apaga um arquivo num lugar que só SYSTEM ou administradores deveriam controlar. O FAQ da Microsoft confirma que a exploração dá ao atacante privilégios de SYSTEM.[1], [2]

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

IMPLEMENTAÇÃO VULNERÁVEL
/* 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;
}
PATCH SEGURO E ROBUSTO
/* 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

Fontes