
VFS para Git ab95cf51 - Medio - Local - Privilegio residual - la tubería del servicio confía en JSON OwnerSID
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · vfs-service-sid
Clase: Privilegio residual Alcance: Local
VFS for Git master ab95cf51 (etiqueta v2.0.26259.1) - Microsoft
GVFS.Service se ejecuta como LocalSystem. WindowsPlatform.CreatePipeByName otorga a BUILTIN\Users ReadWrite | CreateNewInstance sobre GVFS.Service.pipe. RegisterRepoHandler.Run almacena el OwnerSID JSON tal cual. Nada llama a ImpersonateNamedPipeClient.
Cualquier principal de Users puede registrar una ruta del atacante bajo un SID de la víctima. En SessionLogon el servicio hace CreateProcessAsUser de gvfs mount <ruta del atacante> como la víctima. El hijo no es NT AUTHORITY\SYSTEM.
| ID | aún sin CVE |
| Clase | Privilegio residual (autorización faltante / ejecución entre usuarios) |
| Alcance | Local |
| CWE | CWE-862, CWE-284 |
| CVSS | Medio: 6.6 CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:N |
| Producto | VFS for Git |
| Afectado | master ab95cf51d6ffd0ee0e2feae7180078fe9ecbbb3a; etiquetas de GitHub v2.0.26229.1 / v2.0.26259.1. Solo Windows. |
| Auth | Local. Cualquier principal BUILTIN\Users. Inicio de sesión de la víctima para el automontaje. |
| Licencia | GNU Affero GPL v3.0 |
| Lab | Solo 127.0.0.1. how=gadget (sin GVFS.Service de Windows en vivo). |
Git 2.35+ dubious-ownership puede entonces fallar git dentro de un árbol propiedad del atacante. El proceso aún se inicia como la víctima. Si la ruta es propiedad de la víctima pero escribible por el atacante (vfs-clone-acl), mount git, credential.helper y los hooks se ejecutan como ese usuario.
Cualquier principal BUILTIN\Users en una máquina donde el servicio está instalado. Conectarse a \\.\pipe\GVFS.Service.pipe. Sin privilegio adicional.
| Privilegio | Método / sink | Qué otorga | Recon / integridad / disponibilidad | Probado en lab o inferido |
|---|---|---|---|---|
| Listar cada raíz de enlistment activa | GetActiveRepoListRequest sin comprobación de SID (TryGetActiveRepos, no GetActiveReposForUser) | Rutas usadas como oráculo de nombre de pipe para el residual #2 | Recon | Probado en lab. El gadget listó /lab/repos/victim |
| Desactivar un enlistment de la víctima para que no se automonte | UnregisterRepoRequest {EnlistmentRoot} sin comprobación de SID (TryDeactivateRepo) | Los repos de la víctima permanecen desmontados | Disponibilidad | Probado en lab. La fila de la víctima desapareció de la lista activa |
| Persistir la ruta del atacante bajo el SID de la víctima | RegisterRepoRequest JSON EnlistmentRoot + OwnerSID; TryRegisterRepo almacena ambos | Fila de registro ruta del atacante + SID de la víctima | Integridad | Probado en lab. Fila de registro /lab/repos/attacker + S-1-5-21-1000-2000-3000-1001 |
Iniciar GVFS.exe mount <ruta del atacante> como la víctima al iniciar sesión | OnSessionChange SessionLogon -> AutoMountRepos(userId) -> TryRunAs / CreateProcessAsUser | Creación de proceso entre usuarios como el usuario que inicia sesión | Integridad | Probado en lab en el gadget. Padre generado GVFS.Service, argv mount /lab/repos/attacker, uid 1002 victim, testigo escrito |
| Ejecutar como NT AUTHORITY\SYSTEM | Mismo automontaje | Hijo LocalSystem | Integridad | Cerrado. El whoami del hijo es la víctima, no SYSTEM (child-not-system=yes) |
Git / hook / credential.helper como la víctima dentro de un árbol propiedad del atacante | La creación del proceso aún ocurre; git 2.35+ safe.directory puede fallar | RCE por hook como la víctima si el árbol es propiedad de la víctima pero escribible por el atacante | Integridad | Inferido. El lab no ejecutó git de Microsoft. Vincular la ruta como propiedad de la víctima pero escribible por el atacante para RCE por hook |
Cerrado en este pin: acceso remoto no autenticado (el named pipe es local). Shell SYSTEM. La ACL de pipe por defecto aún deja entrar a Users; un registro parcheado que vincula el SID del cliente (gadget X-Patched: 1) no automonta la ruta del atacante para la víctima.
Residuales del mismo pin: vfs-quote-breakout, vfs-mount-dehydrate, vfs-clone-acl, vfs-hook-impersonate, vfs-install-cwd.
Fijé VFSForGit master ab95cf51 tras el merge del 2026-09-28. La ACL del pipe del servicio es Users ReadWrite. Register almacena el OwnerSID JSON. SessionLogon automonta como ese SID. Nada suplanta al cliente del pipe.
Caminos equivocados ya registrados: llamar a esto un shell SYSTEM (el automontaje es CreateProcessAsUser del token de inicio de sesión); tratar git safe.directory como autorización del IPC; una reverse shell. Teatro. Faltaba Windows nativo, así que el lab es un gadget de los handlers del pin más un oráculo TCP de Unix.
python3 vfs-service-sid-Abraxas-Labs.py
o
cd lab
./run.sh
Gadget HTTP en 127.0.0.1:19660. Testigo VFS-SERVICE-SID-WITNESS. La última línea usa how=gadget.
SUCCESS vfs-service-sid how=gadget register-forged-sid=yes automount-as-victim=yes child-not-system=yes VFS-SERVICE-SID-WITNESS
Suplantar al cliente del named-pipe (ImpersonateNamedPipeClient / NamedPipeServerStream.RunAsClient). Ignorar el OwnerSID JSON; vincular TryRegisterRepo al SID del cliente. Restringir CreatePipeByName al usuario interactivo y LocalSystem (eliminar BuiltinUsersSid ReadWrite / CreateNewInstance). GetActiveRepoList debería devolver solo los repos de ese cliente. UnregisterRepo debería requerir la misma coincidencia de SID.