flawopen.com/Incidents/windows-update-stack-symlink-eop-september-2026
CVE-2026-81963: Windows Update 링크 권한 상승
CVE-2026-81963은 악용된 Windows Update 링크 확인 취약점입니다. 영향 버전, Microsoft 수정 사항, 안전한 서비스 파일 처리를 확인하세요.[1], [2]
마스터키를 가진 야간 관리인이 벽의 화살표를 따라 「복도 끝 창고」로 소포를 배달하면서 자기가 어느 방에 들어왔는지는 확인하지 않습니다. 입주자들은 그 화살표를 옮길 수 있습니다. 한 입주자가 창고를 가리키는 화살표를 관리자 사무실 쪽으로 돌려놓자, 어느 문이든 여는 마스터키를 가진 관리인은 안으로 들어가 관리자 책상에 소포를 놓습니다. 그 문은 입주자 스스로는 결코 열 수 없고, 관리인의 키가 대신 열어 준 것입니다. 해결책은 관리인이 실제로 연 문의 번호를 확인하고, 입주자가 옮길 수 있는 화살표는 따르지 않는 것입니다.[5], [9]
핵심 개념 및 용어
Windows 업데이트 스택- 업데이트를 검색·다운로드·스테이징·설치하는 Windows 구성 요소. 업데이트 설치에는 운영 체제의 보호된 영역에 대한 쓰기가 필요하므로 SYSTEM으로 실행됩니다.[1]
SYSTEM(NT AUTHORITY\SYSTEM)- Windows 서비스가 실행되는 로컬 계정. 로컬 컴퓨터에서 관리자보다 강한 권한을 가져, 이 계정의 파일 작업은 거의 거부되지 않습니다.[1]
정션 / 심볼릭 링크(재분석 지점)- 한 경로를 다른 위치로 확인되게 하는 NTFS 개체. 표준 사용자는 자신이 통제하는 폴더에 정션을 만들어 그 이름을 자신이 쓸 수 없는 디렉터리로 돌릴 수 있습니다.[9]
링크 추적(CWE-59)- 프로그램이 이름으로 파일을 열거나 쓰거나 옮기거나 삭제하면서 그 이름이 예상한 위치로 확인되는지 검사하지 않아, 남이 심어 둔 링크가 작업 대상을 바꿔 버리는 것.[5], [2]
FILE_FLAG_OPEN_REPARSE_POINT- 경로의 마지막 구성 요소가 재분석 지점일 때 마지막 링크를 따라가지 않고 해당 지점 자체를 여는 CreateFileW 플래그입니다. 이 플래그만으로 앞선 경로 구성 요소의 재분석 처리가 차단되지는 않습니다.[6]
TOCTOU(CWE-367)- 검사 시점과 사용 시점의 차이. 검사와 그에 의존하는 작업 사이에 파일 시스템이 바뀌는 것. 경로 문자열을 검사한 뒤 이름으로 여는 방식이 바로 그 틈을 남깁니다.[12]
프레임워크 매핑
- 이 가이드에서 설명하는 약점의 CWE 참조: CWE-59 CWE-284
- CISA KEV — 추가일 2026-09-08 — CVE-2026-81963
사고 타임라인
Microsoft가 CVE-2026-81963을 예약한다.[2]
9월 Patch Tuesday: Microsoft가 수정을 공개하고 결함을 「Exploitation Detected」이자 비공개로 표시한다.[1]
CISA가 CVE-2026-81963을 Known Exploited Vulnerabilities 목록에 추가하며, 미국 연방 기관의 수정 기한을 2026년 9월 22일로 정한다.[4]
Microsoft가 권고의 개정판을 공개한다.[1]
단계별 공격 실행 흐름
SYSTEM 서비스가 사용자가 바꿀 수 있는 경로에서 동작한다
업데이트 스택 구성 요소는 SYSTEM으로 실행되며 스테이징·작업 디렉터리에서 파일을 다룹니다. 표준 사용자가 그 경로의 어느 지점에서든 항목을 만들거나 삭제하거나 이름을 바꿀 수 있으면 경로가 어디로 확인될지는 그 사용자가 정합니다. 이번에 어떤 경로가 영향을 받았는지 Microsoft는 밝히지 않았습니다.[1]
소스 코드 비교: 취약한 구현 vs 보안 패치
Microsoft는 영향을 받은 함수나 패치를 공개하지 않았습니다. 이 방어 예시는 Microsoft 코드가 아닙니다. 소유자만 확인하는 것으로는 충분하지 않습니다. 객체의 소유자라는 사실만으로 DACL이 일반 사용자의 쓰기를 거부한다고 볼 수 없습니다. 이 패턴은 설치 프로그램이 고정된 staging 경로와 모든 상위 디렉터리를 SYSTEM 및 Administrators만 쓰도록 허용하는 명시적 DACL로 만든다고 가정합니다. 이 함수는 DACL을 읽거나 검증하지 않습니다. 설치 프로그램이 미리 설정한 권한은 배포 전제 조건입니다. 열린 디렉터리 핸들을 검증한 뒤 NtCreateFile과 FILE_CREATE를 사용해 그 핸들 기준으로 단일 하위 파일 이름을 생성하며, 이어 붙인 경로를 다시 열지 않습니다. 지원되는 배포 환경에서 DACL과 파일 시스템 동작을 검증하세요. CVE-2026-81963을 해결하려면 Microsoft 업데이트를 설치하세요.[5], [6], [7], [8], [9], [10]
소스 코드 발췌: Windows 경로 처리 예시이며 Microsoft 소스 코드는 아닙니다
/* 설명용 예시이며 Microsoft 소스 코드가 아닙니다. 영향을 받은 함수는 공개되지 않았습니다. SYSTEM 권한 서비스가 일반 사용자가 수정할 수
* 있는 staging 디렉터리에 파일을 씁니다.
*/
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는 경로의 각 구성 요소에서 junction과 심볼릭 링크를 해석하며, 접근 검사는 SYSTEM 토큰으로
* 수행됩니다. 사용자가 stagingDir를 junction으로 바꾸면 쓰기가 해당 대상으로 향합니다.
*/
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;
}/* 방어 패턴 예시이며 Microsoft 소스 코드나 패치가 아닙니다. 설치 프로그램은 이 경로와 모든 상위 디렉터리를 명시적 DACL로 만들고 SYSTEM
* 및 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;
/* 디렉터리 객체를 고정합니다. FILE_SHARE_DELETE를 생략하면 이름 변경이 차단됩니다. */
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;
/* 경로를 다시 만들지 말고 이 핸들을 기준으로 새 하위 항목을 엽니다. */
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가 실패합니다. */
DWORD written = 0;
ok = WriteFile(file, data, size, &written, NULL) && written == size;
CloseHandle(file);
done:
CloseHandle(dir);
return ok;
}엔지니어링 및 시스템 보안 강화 체크리스트
- ✓2026년 9월 누적 업데이트를 설치하세요: KB5124008(Windows 11 24H2 및 25H2), KB5122880(23H2), KB5124012(26H1) 또는 KB5122871(Server 2025). 수정된 빌드는 10.0.26100.9445, 10.0.26200.9445, 10.0.22631.7582, 10.0.28000.2954이며 Server 2025는 10.0.26100.33438입니다.[1]
- ✓SYSTEM이나 관리자로 실행되는 모든 서비스에서 경로가 %ProgramData%, %TEMP%, C:\Users 또는 사용자가 쓸 수 있는 다른 위치에 있는 CreateFileW, DeleteFileW, MoveFileExW, CopyFileW, SetFileSecurityW 호출을 모두 나열하고 각각 검토를 의무화하세요.
- ✓디렉터리는 FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT로 열고, FILE_ATTRIBUTE_REPARSE_POINT가 설정된 것은 거부하며, 그 안에서 작업하는 동안 핸들을 FILE_SHARE_DELETE 없이 열어 두세요.[6], [9]
- ✓쓰기 전에 열린 핸들에 대해 GetFinalPathNameByHandleW로 대상을 확인하세요. 직접 만든 경로 문자열은 절대 믿지 마세요.[7]
- ✓공유 디렉터리에서는 CREATE_ALWAYS 대신 CREATE_NEW(NtCreateFile의 FILE_CREATE도 가능)를 사용해, 같은 이름의 파일이나 링크가 있으면 덮어쓰지 말고 작업을 실패시키세요.[8]
- ✓서비스 작업 디렉터리는 SYSTEM과 Administrators에게만 쓰기를 허용하는 명시적 DACL로 만들고, icacls가 Users나 Authenticated Users의 쓰기 권한을 보이면 설치 프로그램 테스트를 실패시키세요.[10]
- ✓서비스가 호출자를 대신해 파일 작업을 수행할 때는 그 호출자를 가장(RpcImpersonateClient, ImpersonateNamedPipeClient)해, 접근이 SYSTEM이 아니라 호출자의 토큰으로 검사되게 하세요.
- ✓표준 사용자 프로세스가 %ProgramData%나 %windir% 아래에 정션이나 마운트 지점을 만들면 경고를 발생시키세요. 정상적인 사용에서는 드물며, 링크 추적 공격은 이렇게 시작됩니다.
- ✓검증된 디렉터리 핸들을 기준으로
NtCreateFile과FILE_CREATE를 사용해 하위 파일을 만드세요. 디렉터리를 확인한 뒤 이어 붙인 경로로stagingDir\name을 다시 열지 마세요.[8]
출처
- Microsoft 보안 대응 센터 — CVE-2026-81963, Windows 업데이트 스택 권한 상승 취약점
- CVE-2026-81963 — CVE 레코드
- NVD — CVE-2026-81963
- CISA — Known Exploited Vulnerabilities 목록
- MITRE CWE-59: 파일 접근 전 잘못된 링크 확인
- 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