
VFS for Git ab95cf51 - High - Local - Privilege leftover - hook CreateFileW SecurityImpersonation
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · vfs-hook-impersonate
Class: Privilege leftover Reach: Local
VFS for Git master ab95cf51 (tag v2.0.26259.1) - Microsoft
Native git hooks (read-object, virtual-filesystem, post-index-changed) open the per-enlistment mount pipe with CreateFileW and dwFlagsAndAttributes = 0. That omits SECURITY_SQOS_PRESENT, so Windows defaults the client to SecurityImpersonation. The same pipe ACL that leftover #2 uses grants BUILTIN\Users ReadWrite | CreateNewInstance.
A second local user can extra-instance or squat \\.\pipe\GVFS_<ENLISTMENT>, ImpersonateNamedPipeClient, and write as the victim.
| ID | no CVE yet |
| Class | Privilege leftover (named-pipe impersonation) |
| Reach | Local |
| CWE | CWE-284, CWE-300 |
| CVSS | High: 7.1 CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N |
| Product | VFS for Git |
| Affected | master ab95cf51d6ffd0ee0e2feae7180078fe9ecbbb3a (also current vs release v2.0.26259.1). Windows only. |
| Auth | Local. Victim has a GVFS enlistment. Attacker is any BUILTIN\Users principal. Victim later runs git. |
| License | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1 only. how=gadget (no live Windows VM / installed VFS for Git). |
This is local. It is not SYSTEM. Automount in leftover #4 is a different pipe (GVFS.Service.pipe). Dehydrate/unmount on this same mount pipe is leftover #2.
Victim has a GVFS enlistment. Attacker is any BUILTIN\Users principal. Victim later runs git (status, checkout, anything that fires the VFS hooks).
| Privilege | Method / sink | What it grants | Recon / integrity / availability | Lab-proven or inferred |
|---|---|---|---|---|
| Impersonate the victim and write into their profile | Extra-instance / squat \\.\pipe\GVFS_C_\REPOS\FOO; hook CreateFileW flags=0; ImpersonateNamedPipeClient; create %USERPROFILE%\VFS-HOOK-IMPERSONATE-WITNESS | Write as the victim UID | Integrity | Lab-proven on a gadget. Witness owner is the victim uid. Default flags are SecurityImpersonation. Attacker uid cannot write that home without impersonation |
| Keep git working after the squat | Reply S|\x03 to MPL|1 so GVFS.VirtualFileSystemHook does not hang | Git continues | Availability of the victim git | Lab-proven. Hook reply_ok on both vuln and patched paths |
| Guess the pipe name from the enlistment root | GetGVFSPipeName walks CWD to .gvfs, CharUpper, : -> _, prefix \\.\pipe\GVFS_ | Guessable IPC name | Recon | Lab-proven. C:\Repos\Foo\src -> \\.\pipe\GVFS_C_\REPOS\FOO |
| Retarget the pipe without winning the live instance | Plant a tracked src\.gvfs directory so the walk-up binds a different name | Squatting without racing the mount | Integrity | Inferred from common.windows.cpp walk-up. Lab used the real enlistment .gvfs |
Answer DLO / PICN as well as MPL | Same pipe, ReadObjectHook / PostIndexChangedHook | Lie about objects / skip-worktree | Integrity | Inferred. Lab sent MPL|1 only |
Crash the hook with a two-byte S\x03 | VirtualFileSystemHook messageLength -= 2 then -= 1 underflows and fwrites ~4GiB | Crash / OOB read | Availability | Inferred from main.cpp 69-90. Not the oracle. Do not ship that crash |
Closed here: SYSTEM (mount is the enlistment user). Remote unauthenticated RCE. Live Windows VM / installed VFS for Git (this lab is a gadget of the copied functions).
Same pin leftovers: vfs-quote-breakout, vfs-mount-dehydrate, vfs-clone-acl, vfs-service-sid, vfs-install-cwd.
I pinned VFSForGit master ab95cf51 after the 2026-09-28 merge. Native hooks CreateFileW with flags 0. Windows then defaults to SecurityImpersonation. The mount pipe already lets Users extra-instance. That is the leftover.
Wrong turns already recorded: treating this as leftover #2 dehydrate (same ACL, different sink: token, not MoveDirectory); claiming SYSTEM; shipping the 4GiB underflow as the oracle. Theatre. Native Windows was missing, so the lab is a gadget of those functions. Unix sockets stand in for named pipes.
python3 vfs-hook-impersonate-Abraxas-Labs.py
or
cd lab
./run.sh
Gadget HTTP on 127.0.0.1:19670. Copies GetGVFSPipeName, CreatePipeToGVFS flags, the Users CreateNewInstance ACL, and the MPL|1 / S| hook protocol. A patched client with SQOS identification does not write the witness. Last line uses how=gadget.
SUCCESS vfs-hook-impersonate how=gadget createfile-flags=0 impersonation=SecurityImpersonation extra-instance=yes owner=victim patched-sqos-ident-no-write=yes VFS-HOOK-IMPERSONATE-WITNESS
On the hook CreateFileW pass SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION. Restrict CreatePipeByName to the enlistment owner SID plus LocalSystem. Drop CreateNewInstance for Users. Bound-check hook reply lengths.
ab95cf51d6ffd0ee0e2feae7180078fe9ecbbb3acommon.windows.cpp CreatePipeToGVFSWindowsPlatform.cs CreatePipeByNameGNU Affero GPL v3.0. See LICENSE. Loopback lab only. No warranty.