
VFS para Git ab95cf51 - Médio - Local - Privilégio remanescente - pipe de serviço confia no JSON OwnerSID
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · vfs-service-sid
Classe: Privilégio remanescente Alcance: Local
VFS for Git master ab95cf51 (tag v2.0.26259.1) - Microsoft
GVFS.Service é executado como LocalSystem. WindowsPlatform.CreatePipeByName concede a BUILTIN\Users ReadWrite | CreateNewInstance em GVFS.Service.pipe. RegisterRepoHandler.Run armazena o JSON OwnerSID como está. Nada chama ImpersonateNamedPipeClient.
Qualquer principal de Users pode registrar um caminho do atacante sob um SID da vítima. No SessionLogon o serviço faz CreateProcessAsUser de gvfs mount <caminho do atacante> como a vítima. O processo filho não é NT AUTHORITY\SYSTEM.
| ID | ainda sem CVE |
| Classe | Privilégio remanescente (autorização ausente / execução entre usuários) |
| Alcance | Local |
| CWE | CWE-862, CWE-284 |
| CVSS | Médio: 6.6 CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:N |
| Produto | VFS for Git |
| Afetado | master ab95cf51d6ffd0ee0e2feae7180078fe9ecbbb3a; tags do GitHub v2.0.26229.1 / v2.0.26259.1. Somente Windows. |
| Autenticação | Local. Qualquer principal BUILTIN\Users. Logon da vítima para automontagem. |
| Licença | GNU Affero GPL v3.0 |
| Lab | Somente 127.0.0.1. how=gadget (sem GVFS.Service do Windows real). |
O dubious-ownership do Git 2.35+ pode então fazer o git falhar dentro de uma árvore pertencente ao atacante. O processo ainda inicia como a vítima. Se o caminho pertence à vítima mas é gravável pelo atacante (vfs-clone-acl), o mount do git, credential.helper e hooks são executados como aquele usuário.
Qualquer principal BUILTIN\Users em uma máquina onde o serviço está instalado. Conecta-se a \\.\pipe\GVFS.Service.pipe. Sem privilégio extra.
| Privilégio | Método / sink | O que concede | Recon / integridade / disponibilidade | Comprovado em lab ou inferido |
|---|---|---|---|---|
| Listar toda raiz de enlistment ativa | GetActiveRepoListRequest sem verificação de SID (TryGetActiveRepos, não GetActiveReposForUser) | Caminhos usados como oráculo de nome de pipe para o leftover #2 | Recon | Comprovado em lab. O gadget listou /lab/repos/victim |
| Desativar um enlistment da vítima para que não automonte | UnregisterRepoRequest {EnlistmentRoot} sem verificação de SID (TryDeactivateRepo) | Repositórios da vítima permanecem desmontados | Disponibilidade | Comprovado em lab. Linha da vítima removida da lista ativa |
| Persistir caminho do atacante sob o SID da vítima | RegisterRepoRequest JSON EnlistmentRoot + OwnerSID; TryRegisterRepo armazena ambos | Linha de registro caminho do atacante + SID da vítima | Integridade | Comprovado em lab. Linha de registro /lab/repos/attacker + S-1-5-21-1000-2000-3000-1001 |
Iniciar GVFS.exe mount <caminho do atacante> como a vítima no logon | OnSessionChange SessionLogon -> AutoMountRepos(userId) -> TryRunAs / CreateProcessAsUser | Criação de processo entre usuários como o usuário do logon | Integridade | Comprovado em lab no gadget. Parent gerado GVFS.Service, argv mount /lab/repos/attacker, uid 1002 victim, witness gravado |
| Executar como NT AUTHORITY\SYSTEM | Mesma automontagem | Filho LocalSystem | Integridade | Fechado. whoami do filho é a vítima, não SYSTEM (child-not-system=yes) |
Git / hook / credential.helper como a vítima dentro de uma árvore pertencente ao atacante | A criação de processo ainda ocorre; git 2.35+ safe.directory pode falhar | RCE via hook como a vítima se a árvore pertence à vítima mas é gravável pelo atacante | Integridade | Inferido. O lab não executou o git da Microsoft. Vincule o caminho como pertencente à vítima mas gravável pelo atacante para RCE via hook |
Fechado neste pin: acesso remoto não autenticado (named pipe é local). Shell SYSTEM. A ACL padrão do pipe ainda permite Users; um register corrigido que vincula o SID do cliente (gadget X-Patched: 1) não automonta o caminho do atacante para a vítima.
Outros leftovers do mesmo pin: vfs-quote-breakout, vfs-mount-dehydrate, vfs-clone-acl, vfs-hook-impersonate, vfs-install-cwd.
Fiz o pin do VFSForGit master ab95cf51 após o merge de 2026-09-28. A ACL do pipe do serviço é Users ReadWrite. O Register armazena o JSON OwnerSID. O SessionLogon automonta como aquele SID. Nada personifica o cliente do pipe.
Caminhos errados já registrados: chamar isso de shell SYSTEM (a automontagem é CreateProcessAsUser do token de logon); tratar o git safe.directory como autorização do IPC; um reverse shell. Teatro. O Windows nativo estava ausente, então o lab é um gadget dos handlers do pin mais um oráculo TCP Unix.
python3 vfs-service-sid-Abraxas-Labs.py
ou
cd lab
./run.sh
Gadget HTTP em 127.0.0.1:19660. Witness VFS-SERVICE-SID-WITNESS. A última linha 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
Personifique o cliente do named pipe (ImpersonateNamedPipeClient / NamedPipeServerStream.RunAsClient). Ignore o JSON OwnerSID; vincule TryRegisterRepo ao SID do cliente. Restrinja CreatePipeByName ao usuário interativo e ao LocalSystem (remova BuiltinUsersSid ReadWrite / CreateNewInstance). GetActiveRepoList deve retornar apenas os repositórios daquele cliente. UnregisterRepo deve exigir a mesma correspondência de SID.