
CVE-2026-42978 — Windows 푸시 알림(WpnService)의 Use-After-Free 경쟁 조건. 패치 diff, 근본 원인 분석, TOCTOU 랩, Sysmon/ETW 탐지 규칙.
Windows Push Notifications 서비스(WpnService)의 경쟁 조건(Race Condition) 취약점으로, NT AUTHORITY\SYSTEM 권한으로 실행됩니다. 로컬 접근 권한이 있는 공격자는 플랫폼 종료 중에 use-after-free를 유발하여 권한을 상승시킬 수 있습니다.
WpnService는 Windows 푸시 알림 서비스입니다. 세션 0에서 svchost.exe -k netsvcs -p 내부의 LocalSystem으로 실행됩니다. 모든 알림 전달(토스트, 타일, 배지)은 이 서비스를 통해 이루어집니다.
취약점은 wpncore.dll의 PresentationEndpointFacade 클래스에 있습니다. 이 클래스는 모든 알림 API 호출(토스트 전달, 세션 관리, 설정 조회 등)을 래핑하고 PresentationEndpointImpl에 위임합니다.
버그: 플랫폼 종료 중에 NotificationPlatform 개체가 소멸됩니다. 그러나 Facade 메서드는 종료가 진행 중인지 확인하지 않습니다. 플랫폼에 대한 포인터를 가져온 다음, 종료 스레드가 플랫폼을 해제하고, Facade는 댕글링 포인터를 사용합니다. 전형적인 use-after-free 경쟁 조건입니다.
// PresentationEndpointFacade::ToastUnblockAll — 취약
long ToastUnblockAll(PresentationEndpointFacade *this) {
// 잠금 없음. 종료 확인 없음. 그냥 플랫폼 포인터를 가져와서 진행.
NotificationPlatformHandle::Get(this + 0x50);
if (platform == NULL) Throw_Hr(...);
// 종료가 바로 여기서 플랫폼을 해제하면 — use-after-free
return PresentationEndpointImpl::UnblockToastsForEachApp(...);
}
Ghidra: 취약한 ToastUnblockAll — 플랫폼 접근 전 동기화 없음
// PresentationEndpointFacade::ToastUnblockAll — 패치됨
long ToastUnblockAll(PresentationEndpointFacade *this) {
if (Feature_4097557817::IsEnabled()) {
AcquireSRWLockShared(&Wns::s_platformLock); // 1. 공유 잠금
if (Wns::s_platformShutdown) // 2. 종료 가드
Throw_Hr(E_APPLICATION_EXITING);
NotificationPlatformHandle::Get(this + 0x50);
// ... 작업 수행 ...
ReleaseSRWLockShared(&Wns::s_platformLock); // 3. RAII 해제
} else {
// 기능 플래그 꺼짐 — 롤백을 위해 이전 동작 유지
}
}
수정은 세 가지를 추가합니다:
AcquireSRWLockShared — 공유 readers-writer 잠금. 여러 API 호출이 동시에 실행될 수 있지만, 종료는 배타적 잠금을 획득하여 모두 차단합니다.s_platformShutdown 확인 — 종료가 이미 시작된 경우 E_APPLICATION_EXITING으로 즉시 중단합니다.wil::unique_storage 래퍼에 보관되므로 예외가 발생해도 해제됩니다.기능 플래그 Feature_4097557817는 WIL(Windows Internal Library)을 통한 단계적 배포를 위한 것입니다. Microsoft가 수정 사항을 점진적으로 활성화하고 문제가 발생하면 비활성화할 수 있게 해줍니다.
이것은 단일 함수 버그가 아닙니다. 동일한 잠금+가드 패턴이 wpncore.dll의 49개 함수에 추가되었습니다:
| 카테고리 | 함수 |
|---|---|
| 토스트 작업 | ToastUnblockAll, ToastCreateSession, ToastCloseSession, ToastRequestAllNotifications, ToastSuppress |
| 타일 작업 | TileCreateSession, TileCloseSession, TileRequestResourceForeground |
| 등록 | RegisterApplication, UnregisterApplication, RegisterHandler, UpdateRegistration, RegisterSystemApplication |
| 설정 | ChangeAppSetting, QueryAppSetting, QueryGlobalSetting, RegisterSettingCallback, UnregisterSettingCallback |
| 전달 | Deliver, GetPayloadForNotificationId, Submit, PostScheduledNotification |
| 쿼리 | GetRegisteredHandler, GetRegisteredHandlersFromParent, GetSettingsFromHandler, GetAssetsFromHandler |
플랫폼에 접근하는 모든 PresentationEndpointFacade::* 메서드에 동일한 수정이 적용되었습니다. 내부의 PresentationEndpointImpl::* 메서드는 변경되지 않았습니다. 문제는 Facade 계층에만 있었습니다.
WpnService는 SYSTEM 권한으로 실행됩니다. 경쟁 조건에서 승리하면:
NotificationPlatform 개체의 메모리를 재확보하여 공격자 제어 데이터로 채울 수 있습니다(힙 스프레이)NT AUTHORITY\SYSTEM 권한으로 코드 실행실제 악용(힙 스프레이, vtable 하이재킹, 코드 실행 달성)은 이 연구의 범위를 벗어납니다. 이 저장소는 근본 원인 이해와 탐지 구축에 중점을 둡니다.
lab/ 디렉터리에는 WpnService를 건드리지 않고 이 버그 유형을 재현하는 독립형 C 데모가 포함되어 있습니다. WpnService와 유사한 명명된 파이프 + 공유 메모리 아키텍처를 사용합니다.
작동 방식:
vulnerable_service.exe는 공유 메모리에서 메시지 길이를 읽고, 검증하고, 50ms 동안 대기한 다음, 길이를 다시 읽습니다(이중 페치).race_attacker.exe는 안전한 길이를 설정하고 서비스를 트리거한 다음 즉시 공유 메모리를 오버플로 값으로 변경합니다.로컬 변수로의 단일 페치 캡처인 수정 사항을 보려면 vulnerable_service.exe --patched를 실행하세요.
왼쪽: 서비스가 경쟁 조건 감지(5/5). 오른쪽: 공격자가 공유 메모리 값 변경.
GCC(MinGW)가 필요합니다. lab/ 디렉터리에서:
build.bat
터미널 1:
vulnerable_service.exe
터미널 2:
race_attacker.exe 5
그런 다음 vulnerable_service.exe --patched와 비교하세요 — 동일한 공격, 경쟁 조건 0회 감지.
detection/etw_wpn_monitor.ps1)7가지 지표를 확인하는 PowerShell 스크립트:
powershell -ExecutionPolicy Bypass .\detection\etw_wpn_monitor.ps1
ETW 모니터: WpnService 실행 중(PID 6432), 크래시 없음, 시간당 100개 이벤트, 시스템 패치됨
detection/sysmon_wpn_race_detect.xml)지속적 모니터링을 위한 6개 규칙 그룹:
| 규칙 | 탐지 내용 |
|---|---|
WPN_EoP_ChildProcess | svchost(netsvcs)가 cmd/powershell/wscript 생성 |
WPN_PipeAccess | WPN 관련 명명된 파이프에 대한 연결 |
WPN_FileCreation | 알림 데이터 디렉터리에 파일 생성 |
WPN_RegistryTampering | PushNotifications 키에 레지스트리 쓰기 |
WPN_ProcessAccess | svchost에 대한 PROCESS_ALL_ACCESS 핸들 |
WPN_ThreadInjection | svchost에 CreateRemoteThread |
설치:
sysmon64.exe -accepteula -i detection\sysmon_wpn_race_detect.xml
WpnService 활동은 Microsoft-Windows-PushNotifications-Platform/Operational에 기록됩니다. 주목해야 할 주요 이벤트:
이벤트 뷰어: PushNotifications-Platform 운영 로그, 이벤트 ID 1225
wpncore.dll 디퓨징의 주요 발견:
.text 섹션이 18,432바이트 증가(49개 함수에 새 잠금/가드 코드).data 섹션이 96바이트 증가(새 Wns::s_platformLock 및 Wns::s_platformShutdown 전역 변수)AcquireSRWLockShared/ReleaseSRWLockShared는 이미 임포트 테이블에 있었습니다~unique_any_t<...ReleaseSRWLockExclusive...>는 잠금 래퍼 추가를 확인합니다전체 보고서는 reports/에 있습니다.
CVE-2026-42978은 2026년 6월에 수정된 9개의 WPN 관련 취약점 클러스터의 일부입니다:
| CVE | 유형 | CWE |
|---|---|---|
| CVE-2026-42977 | EoP | 경쟁 조건 |
| CVE-2026-42978 | EoP | 경쟁 조건 |
| CVE-2026-42979 | EoP | 경쟁 조건 |
| CVE-2026-42991 | EoP | 경쟁 조건 |
| CVE-2026-42969 | 정보 공개 | 경쟁 조건 |
| CVE-2026-42970 | 정보 공개 | 경쟁 조건 |
| CVE-2026-42973 | 정보 공개 | 경쟁 조건 |
| CVE-2026-26167 | EoP | — |
| CVE-2026-32160 | EoP | — |