
VFS for Git ab95cf51 — Средний — Локальный — Остаточные привилегии — service pipe доверяет JSON OwnerSID
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · vfs-service-sid
Класс: Остаточные привилегии Доступ: Локальный
VFS for Git master ab95cf51 (тег v2.0.26259.1) - Microsoft
GVFS.Service работает как LocalSystem. WindowsPlatform.CreatePipeByName предоставляет BUILTIN\Users права ReadWrite | CreateNewInstance на GVFS.Service.pipe. RegisterRepoHandler.Run сохраняет JSON OwnerSID как есть. Ничто не вызывает ImpersonateNamedPipeClient.
Любой субъект Users может зарегистрировать путь атакующего под SID жертвы. При SessionLogon служба выполняет CreateProcessAsUser для gvfs mount <путь атакующего> от имени жертвы. Дочерний процесс не является NT AUTHORITY\SYSTEM.
| ID | CVE пока нет |
| Класс | Остаточные привилегии (отсутствие авторизации / межпользовательское выполнение) |
| Доступ | Локальный |
| CWE | CWE-862, CWE-284 |
| CVSS | Средний: 6.6 CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:N |
| Продукт | VFS for Git |
| Затронуто | master ab95cf51d6ffd0ee0e2feae7180078fe9ecbbb3a; теги GitHub v2.0.26229.1 / v2.0.26259.1. Только Windows. |
| Аутентификация | Локальная. Любой субъект BUILTIN\Users. Вход жертвы для автомонтирования. |
| Лицензия | GNU Affero GPL v3.0 |
| Лаборатория | Только 127.0.0.1. how=gadget (без живого Windows GVFS.Service). |
Git 2.35+ dubious-ownership может затем привести к сбою git внутри дерева, принадлежащего атакующему. Процесс всё равно запускается от имени жертвы. Если путь принадлежит жертве, но доступен для записи атакующему (vfs-clone-acl), mount git, credential.helper и хуки выполняются от имени этого пользователя.
Любой субъект BUILTIN\Users на машине, где установлена служба. Подключение к \\.\pipe\GVFS.Service.pipe. Без дополнительных привилегий.
| Привилегия | Метод / точка назначения | Что даёт | Разведка / целостность / доступность | Доказано в лаборатории или выведено |
|---|---|---|---|---|
| Перечислить все активные корни enlistment | GetActiveRepoListRequest без проверки SID (TryGetActiveRepos, а не GetActiveReposForUser) | Пути, используемые как оракул имён каналов для остатка #2 | Разведка | Доказано в лаборатории. Gadget перечислил /lab/repos/victim |
| Деактивировать enlistment жертвы, чтобы он не автомонтировался | UnregisterRepoRequest {EnlistmentRoot} без проверки SID (TryDeactivateRepo) | Репозитории жертвы остаются несмонтированными | Доступность | Доказано в лаборатории. Строка жертвы исчезла из активного списка |
| Сохранить путь атакующего под SID жертвы | RegisterRepoRequest JSON EnlistmentRoot + OwnerSID; TryRegisterRepo сохраняет оба | Строка реестра: путь атакующего + SID жертвы | Целостность | Доказано в лаборатории. Строка реестра /lab/repos/attacker + S-1-5-21-1000-2000-3000-1001 |
Запустить GVFS.exe mount <путь атакующего> от имени жертвы при входе | OnSessionChange SessionLogon -> AutoMountRepos(userId) -> TryRunAs / CreateProcessAsUser | Межпользовательское создание процесса от имени вошедшего пользователя | Целостность | Доказано в лаборатории на gadget. Родитель GVFS.Service, argv mount /lab/repos/attacker, uid 1002 victim, свидетель записан |
| Выполнение как NT AUTHORITY\SYSTEM | Тот же автомонтирование | Дочерний процесс LocalSystem | Целостность | Закрыто. Дочерний whoami — это жертва, а не SYSTEM (child-not-system=yes) |
Git / хук / credential.helper от имени жертвы внутри дерева, принадлежащего атакующему | Создание процесса всё равно происходит; git 2.35+ safe.directory может дать сбой | RCE через хук от имени жертвы, если дерево принадлежит жертве, но доступно для записи атакующему | Целостность | Выведено. Лаборатория не запускала Microsoft git. Привяжите путь как принадлежащий жертве, но доступный для записи атакующему, для RCE через хук |
Закрыто на этом пине: удалённый неаутентифицированный доступ (именованный канал локальный). SYSTEM shell. ACL канала по умолчанию всё ещё пропускает Users; пропатченная регистрация, привязывающая SID клиента (gadget X-Patched: 1), не автомонтирует путь атакующего для жертвы.
Остатки того же пина: vfs-quote-breakout, vfs-mount-dehydrate, vfs-clone-acl, vfs-hook-impersonate, vfs-install-cwd.
Я зафиксировал VFSForGit master ab95cf51 после слияния 2026-09-28. ACL канала службы — Users ReadWrite. Register сохраняет JSON OwnerSID. SessionLogon выполняет автомонтирование под этим SID. Ничто не имперсонирует клиента канала.
Уже зафиксированные ошибочные пути: называть это SYSTEM shell (автомонтирование — это CreateProcessAsUser с токеном вошедшего пользователя); рассматривать git safe.directory как авторизацию IPC; обратный шелл. Театр. Нативная Windows отсутствовала, поэтому лаборатория — это gadget из обработчиков пина плюс Unix TCP-оракул.
python3 vfs-service-sid-Abraxas-Labs.py
или
cd lab
./run.sh
Gadget HTTP на 127.0.0.1:19660. Свидетель VFS-SERVICE-SID-WITNESS. Последняя строка использует how=gadget.
SUCCESS vfs-service-sid how=gadget register-forged-sid=yes automount-as-victim=yes child-not-system=yes VFS-SERVICE-SID-WITNESS
Имперсонируйте клиента именованного канала (ImpersonateNamedPipeClient / NamedPipeServerStream.RunAsClient). Игнорируйте JSON OwnerSID; привяжите TryRegisterRepo к SID клиента. Ограничьте CreatePipeByName интерактивным пользователем и LocalSystem (уберите BuiltinUsersSid ReadWrite / CreateNewInstance). GetActiveRepoList должен возвращать только репозитории этого клиента. UnregisterRepo должен требовать совпадения того же SID.