CVE-2022-22715 — Named Pipe File System Elevation of Privilege Vulnerability
Executive Summary
"Windows Dirty Pipe." An integer-overflow-to-out-of-bounds-write in the Named Pipe File System driver (npfs.sys), reachable only from an AppContainer or restricted (sandboxed) token - making it a renderer/UWP sandbox-escape rather than an ordinary local EoP (it was used at TianfuCup 2021 to escape the Adobe Reader sandbox). Opening \Device\NamedPipe\LOCAL\<name> reaches NpTranslateContainerLocalAlias, which rewrites the name into the AppContainer object namespace and sizes a pool buffer using 16-bit (ushort) arithmetic. A sufficiently long pipe name wraps the size to 0 (yielding a tiny 0x20 allocation) while the UNICODE_STRING MaximumLength, decremented past 0, underflows to 0xFFFE; RtlUnicodeStringPrintf then writes ~64 KB of attacker-controlled name into the tiny buffer - a controlled paged-pool overflow that can be groomed (WNF + _TOKEN objects) into arbitrary kernel read/write and SYSTEM. Microsoft's February 2022 fix widens the size arithmetic to 32-bit and adds a bound check (allocate only when the length is < 0xFFFF); the fix is unconditional (no feature flag). Reported by k0shl of Kunlun Lab. Confirmed by an in-house binary diff of npfs.sys 10.0.18362.267 -> .2094.
Overview
CVSS Vector
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H/E:U/RL:O/RC:C
EPSS Score
Affected Products
| Product | KB Article | Severity | Impact | Restart Required |
|---|---|---|---|---|
| Windows 10 Version 1809 for 32-bit Systems | 5010351 (Security Update) |
Important | Elevation of Privilege | Yes |
| Windows 10 Version 1809 for ARM64-based Systems | 5010351 (Security Update) |
Important | Elevation of Privilege | Yes |
| Windows 10 Version 1809 for x64-based Systems | 5010351 (Security Update) |
Important | Elevation of Privilege | Yes |
| Windows 10 Version 1909 for 32-bit Systems | 5010345 (Security Update) |
Important | Elevation of Privilege | Yes |
| Windows 10 Version 1909 for ARM64-based Systems | 5010345 (Security Update) |
Important | Elevation of Privilege | Yes |
| Windows 10 Version 1909 for x64-based Systems | 5010345 (Security Update) |
Important | Elevation of Privilege | Yes |
| Windows 10 Version 20H2 for 32-bit Systems | 5010342 (Security Update) |
Important | Elevation of Privilege | Yes |
| Windows 10 Version 20H2 for ARM64-based Systems | 5010342 (Security Update) |
Important | Elevation of Privilege | Yes |
| Windows 10 Version 20H2 for x64-based Systems | 5010342 (Security Update) |
Important | Elevation of Privilege | Yes |
| Windows 10 Version 21H1 for 32-bit Systems | 5010342 (Security Update) |
Important | Elevation of Privilege | Yes |
| Windows 10 Version 21H1 for ARM64-based Systems | 5010342 (Security Update) |
Important | Elevation of Privilege | Yes |
| Windows 10 Version 21H1 for x64-based Systems | 5010342 (Security Update) |
Important | Elevation of Privilege | Yes |
| Windows 10 Version 21H2 for 32-bit Systems | 5010342 (Security Update) |
Important | Elevation of Privilege | Yes |
| Windows 10 Version 21H2 for ARM64-based Systems | 5010342 (Security Update) |
Important | Elevation of Privilege | Yes |
| Windows 10 Version 21H2 for x64-based Systems | 5010342 (Security Update) |
Important | Elevation of Privilege | Yes |
| Windows 11 version 21H2 for ARM64-based Systems | 5010386 (Security Update) |
Important | Elevation of Privilege | Yes |
| Windows 11 version 21H2 for x64-based Systems | 5010386 (Security Update) |
Important | Elevation of Privilege | Yes |
| Windows Server 2019 | 5010351 (Security Update) |
Important | Elevation of Privilege | Yes |
| Windows Server 2019 (Server Core installation) | 5010351 (Security Update) |
Important | Elevation of Privilege | Yes |
| Windows Server 2022 5010354 (Security Update) 5010456 (Security Hotpatch Update) Important Elevation of Privilege 5009555 Base: 7.8 Temporal: 6.8 Vector: CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H/E:U/RL:O/RC:C 10.0.20348.524 10.0.20348.525 Yes 5010354 Windows Server 2022 (Server Core installation) 5010354 (Security Update) 5010456 (Security Hotpatch Update) Important Elevation of Privilege 5009555 Base: 7.8 Temporal: 6.8 Vector: CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H/E:U/RL:O/RC:C 10.0.20348.524 10.0.20348.525 Yes 5010354 Windows Server, version 20H2 (Server Core Installation) | 5010342 (Security Update) |
Important | Elevation of Privilege | Yes |
Patches
| Article | Type | Restart |
|---|---|---|
5010351 |
Security Update | Yes |
5010345 |
Security Update | Yes |
5010342 |
Security Update | Yes |
5010386 |
Security Update | Yes |
Patch Diff
"Windows Dirty Pipe": a 16-bit integer overflow -> pool out-of-bounds write in npfs.sys NpTranslateContainerLocalAlias, reachable ONLY from an AppContainer/restricted (sandboxed) token - a renderer/UWP sandbox escape (used at TianfuCup 2021 to escape the Adobe Reader sandbox). Opening \Device\NamedPipe\LOCAL\<name> routes NpFsdCreate -> NpTranslateAlias (matches the LOCAL\ prefix) -> NpTranslateContainerLocalAlias, which rewrites the name into Sessions\<n>\AppContainerNamedObjects\<sid>\...\<name>. All size vars were 16-bit: total = prefix + namelen + 0x14 (+2 if the remaining name starts with '\'); a long pipe name wraps this ushort to 0, so ExAllocatePoolWithTag returns a tiny 0x20 'NpFn' buffer, and the UNICODE_STRING MaximumLength decremented past 0 underflows to 0xFFFE. RtlUnicodeStringPrintf then writes ~64KB of attacker-controlled name bytes into the 0x20 pool -> controlled paged-pool OOB write (CWE-190 -> CWE-787). The trigger needs the total size to wrap to exactly 0. IN-HOUSE ghidriff diff of 10.0.18362.267 -> .2094 confirms NpTranslateContainerLocalAlias is the ONLY changed function (99.8% match): the fix widens the size arithmetic from short to 32-bit int/uint (iVar5/iVar10/uVar6) and adds a bound check `if (uVar6 < 0xffff)` before ExAllocatePoolWithTag, eliminating both the overflow and the 0xFFFE underflow. UNCONDITIONAL fix - no CFR/KIR flag. k0shl's PoC chains WNF _WNF_STATE_DATA + _TOKEN grooming into arbitrary R/W and sets ETHREAD.PreviousMode=0. Credit: k0shl of Kunlun Lab via TianfuCup 2021.
| Function | Address | Change | Note |
|---|---|---|---|
NpTranslateContainerLocalAlias |
99.8% match (only changed function) |
code (size arithmetic widened short->int + `< 0xffff` bound check, unconditional) | Pre: 16-bit size vars (short sVar5/sVar10); total = (short)prefix + 100 + (ushort)namelen (+2 if ifslash) wraps to 0 -> ExAllocatePoolWithTag(PagedPool, sVar5, 'NpFn') tiny alloc; MaximumLength -= 2 underflows 0 -> 0xFFFE; RtlUnicodeStringPrintf OOB-writes ~64KB. Post: iVar5/iVar10/uVar6 computed as 32-bit uint (no 16-bit wrap) and `if (uVar6 < 0xffff)` gates the allocation. Reached only when the token is AppContainer or restricted (SeQueryInformationToken TokenIsAppContainer/TokenIsRestricted). |
Attack Path
A long LOCAL\ pipe name wraps a 16-bit size to 0 (tiny pool) while MaximumLength underflows to 0xFFFE, so the name format-copy overruns paged pool - from inside a sandbox
Derived from the patch delta: the checks added by the vendor identify which fields crossed a trust boundary unvalidated. Reachability and privilege are taken from the call chain in the RCA report.
Known Exploits
Acknowledgments
Kunlun lab (https://www.cyberkl.com) via TianfuCup (https://www.tianfucup.com)