Defina o atributo primaryGroupID de uma conta de usuário como 512 e ela se torna membro pleno de Domain Admins em todo login. Isso é a falsificação de primaryGroupID: Domain Admins ocultos que o próprio Active Directory calcula diretamente no token Kerberos da conta, mas que o ADSI Edit, um filtro LDAP bruto (member=...) e a maioria das exportações de auditoria nunca veem — porque apenas metade de como o AD calcula a associação a grupos está de fato armazenada no objeto do grupo.
O que é a primaryGroupID
Todo objeto de usuário e computador do Active Directory carrega um atributo primaryGroupID: um único número inteiro que armazena o Relative Identifier (RID) do grupo primário da conta. É um resquício dos requisitos de compatibilidade POSIX do Windows NT, de antes de o AD suportar grupos aninhados arbitrários, e hoje permanece, na maioria das vezes, intocado em seu valor padrão — a ponto de uma thread recente no r/activedirectory simplesmente perguntar para que serve o campo "Primary Group" em um objeto de usuário.
Os valores padrão, confirmados junto à própria documentação da Microsoft sobre auditoria de eventos e à pesquisa da Semperis sobre o atributo:
| Tipo de objeto | primaryGroupID padrão | Nome do grupo |
|---|---|---|
| Usuário | 513 | Domain Users |
| Computador | 515 | Domain Computers |
| Controlador de domínio | 516 | Domain Controllers |
| DC somente leitura | 521 | Read-only Domain Controllers |
O que importa para este artigo: o RID 512 é Domain Admins.
Diferente da associação a grupo comum — que vive no atributo multivalorado member do objeto de grupo, com um link reverso memberOf correspondente no usuário — a associação ao grupo primário é armazenada apenas na conta, como um único número inteiro. O próprio objeto de grupo não registra nada sobre isso.
Como o Active Directory realmente calcula "quem está neste grupo"
"Quem está em Domain Admins" não é uma única consulta. A associação efetiva é a união de duas coisas separadas:
- Toda conta listada no atributo
memberdo grupo Domain Admins. - Toda conta cujo atributo
primaryGroupIDseja igual a 512 — o RID de Domain Admins — independentemente do que o atributomemberdiga.
Apenas a primeira metade fica armazenada no objeto de grupo. A segunda metade fica inteiramente na conta, e nada no grupo registra que esse vínculo existe. Ferramentas que resolvem a associação consultando diretamente o objeto de grupo reconstroem as duas metades e mostram o quadro completo. Ferramentas que apenas leem o valor bruto de member veem só a primeira metade.
A pesquisa da TrustedSec sobre esse comportamento (Brandon Colley, publicada em janeiro de 2026) demonstra a divisão diretamente: consultar Get-ADGroupMember "Domain Admins" contra o grupo retorna uma conta cujo acesso a Domain Admins vem puramente de primaryGroupID — o cmdlet resolve a união. O Active Directory Users and Computers e o Active Directory Administrative Center fazem o mesmo ao abrir a aba Members do grupo. Mas a mesma pesquisa mostra duas ferramentas caindo do outro lado dessa divisão:
- O ADSI Edit, navegando diretamente pelo atributo
member, não lista a conta. - Um filtro LDAP bruto como
(member=CN=...)— o tipo sobre o qual a maioria dos scripts de exportação caseiros, jobs de relatório baseados em CSV e pipelines de ingestão de SIEM são construídos — também não a detecta, pelo mesmo motivo: está consultando o atributo que nunca foi tocado.
A mesma pesquisa mostra uma segunda lacuna, mais estreita: Get-ADGroupMember -Recursive percorre grupos aninhados para expandir a associação, mas não captura uma conta cujo grupo primário esteja definido como um grupo aninhado dentro de Domain Admins, em vez de Domain Admins propriamente dito. A recursão expande a cadeia de member; ela não reexecuta a união de primaryGroupID em cada nível de aninhamento — o mesmo ponto cego transitivo já coberto em aninhamento perigoso de grupos.
Falsificação de primaryGroupID: Domain Admins ocultos que o Active Directory nunca lista
Um atacante (ou um script) com acesso de escrita ao atributo primaryGroupID de um usuário-alvo — um direito GenericWrite, GenericAll ou WriteProperty delegado em algum ponto abaixo de uma OU, a mesma classe de abuso de ACL que o BloodHound já mapeia em objetos de usuário — define-o como 512. O Active Directory só aceita essa escrita em uma conta que já seja membro explícito do grupo alvo — a própria orientação da Microsoft sobre como definir o grupo primário programaticamente e a pesquisa da Tenable sobre esse atributo confirmam que um simples Set-ADUser -Replace @{primaryGroupID=512} falha contra uma conta que ainda não é membro, e que apenas um bypass do serviço de diretório como o DCShadow consegue defini-lo em uma conta que nunca foi membro. O caminho comum são três comandos, não um:
Add-ADGroupMember -Identity "Domain Admins" -Members jdoe
Set-ADUser -Identity jdoe -Replace @{primaryGroupID=512}
Remove-ADGroupMember -Identity "Domain Admins" -Members jdoe -Confirm:$false
Na próxima solicitação de TGT Kerberos da conta, o RID do grupo primário é incorporado ao token exatamente como qualquer outro SID de grupo. A conta passa a autenticar com acesso equivalente a Domain Admins. Assim que o terceiro comando é concluído, o atributo member de Domain Admins volta à sua lista original, então um diff agendado de exportações de grupo ou uma leitura estática do atributo member não têm mais nada a capturar depois do fato — embora a breve adição e remoção gerem, cada uma, um evento padrão de alteração de associação a grupo ao longo do caminho, de modo que um alerta em tempo real sobre esses eventos específicos (ao contrário de um diff periódico de exportação) tem, sim, um momento para capturá-lo. É por isso que a técnica se resume a falsificação de primaryGroupID: Domain Admins ocultos que o próprio Active Directory calcula em todo token, mas que o controle criado para detectar novos admins nunca vê.
O pesquisador de segurança Yuval Gordon documenta, em um post no blog da Semperis, uma extensão adicional dessa ideia: combinar a alteração de primaryGroupID com uma entrada de controle de acesso de negação de leitura no próprio atributo primaryGroupID do usuário, de forma que mesmo as ferramentas cientes da união (ADUC, Get-ADGroupMember) não consigam mais ler o valor e parem de reportar a associação. É uma técnica real — mas Gordon é explícito sobre onde ela deixa de funcionar:
"Esse truque legal não funciona em membros de grupos protegidos como Domain Admins... essa técnica não funcionará em membros de nenhum grupo protegido pelo processo SDPROP e pelo AdminSDHolder, já que dependemos da DACL, que nesse caso simplesmente será revertida para a DACL do AdminSDHolder a cada hora, aproximadamente."
O ciclo SDProp do AdminSDHolder (a cada 60 minutos, aproximadamente) reaplica uma ACL modelo a qualquer conta que considere membro de um grupo protegido, o que apaga o ACE de negação. Como uma simples alteração de primaryGroupID=512 não toca em nada na DACL da conta, o SDProp não a reverte — ele apenas neutraliza o truque de esconder via ACE de negação, não a falsificação subjacente. O próprio exemplo funcional de Gordon tem como alvo um grupo de teste não protegido, não o DnsAdmins em si — o mesmo post observa, à parte, que a técnica também funciona contra grupos comuns como o DnsAdmins, que tem seu próprio caminho bem conhecido até Domain Admins. A versão simples — definir primaryGroupID diretamente como 512, sem o ACE — não é afetada pelo AdminSDHolder de nenhuma forma, e é exatamente por isso que vale a pena auditá-la diretamente.
Detecção
Este é um caso em que o monitoramento de IDs de evento do Windows realmente funciona a seu favor. A própria referência de auditoria de segurança da Microsoft para o Evento ID 4738 ("Uma conta de usuário foi alterada", sob a subcategoria Audit User Account Management) documenta um campo Primary Group ID nos dados de atributos alterados do evento, e sua própria tabela de recomendação de monitoramento afirma isso claramente:
| Campo a monitorar | Motivo para monitorar |
|---|---|
| Primary Group ID não é 513 | Normalmente, o valor de Primary Group é 513 para usuários de domínio e locais. Outros valores devem ser monitorados. |
Duas verificações independentes, correspondendo às duas coisas que realmente precisam ser capturadas:
Tempo real — auditar a alteração em si
Com Audit User Account Management habilitado, toda escrita em primaryGroupID gera o Evento ID 4738 no DC que processou a alteração, com o novo RID no campo Primary Group ID. Alerte para qualquer 4738 em que esse campo esteja preenchido e o novo valor não seja 513 (ou 515/516/521 para computadores e DCs).
Ponto no tempo — varrer contas já falsificadas
A pesquisa da TrustedSec traz um one-liner direto para isso:
Get-ADUser -property primaryGroup,primaryGroupID -Filter {-not(primaryGroupID -like "513")}
Executado contra um domínio com uma baseline limpa, os únicos resultados devem ser controladores de domínio (516), RODCs (521) e — se seu ambiente ainda os provisiona — contas de serviço mapeadas para POSIX com motivo documentado. Qualquer conta de usuário comum mostrando 512, ou qualquer RID privilegiado que não deveria ter, é o achado.
Nenhuma das duas verificações depende de ler o objeto de grupo Domain Admins — e esse é exatamente o ponto. Uma revisão construída sobre Get-ADGroupMember "Domain Admins" executada diretamente contra o grupo também capturaria isso, segundo a mesma pesquisa; uma revisão construída sobre uma exportação LDAP do atributo member, ou uma ferramenta que trata essa exportação como verdade absoluta, não captará.
Remediation
- Execute a varredura acima em todos os domínios da floresta, não apenas naquele que hospeda Domain Admins — o abuso de primaryGroupID contra um grupo aninhado/local em um domínio filho é tão invisível quanto para exportações do atributo
member. - Redefina qualquer conta não conforme para seu padrão correto (513 para usuários padrão), a menos que haja um motivo de negócio documentado e atual para um valor diferente.
- Habilite Audit User Account Management em todos os controladores de domínio, caso ainda não esteja, para que o Evento ID 4738 seja de fato gerado e encaminhado ao seu SIEM.
- Reconstrua qualquer revisão automatizada de acesso privilegiado que consulte
memberdiretamente — via ADSI Edit, um filtro LDAP bruto(member=...)ou um script de exportação construído da mesma forma — para, em vez disso, chamarGet-ADGroupMembercontra o grupo, ou unir explicitamente uma varredura deprimaryGroupID. A revisão que deveria ser a rede de segurança é precisamente o controle que essa técnica derrota. - Audite quem detém
WriteProperty/GenericWrite/GenericAllem objetos de usuário e quem pode adicionar membros ao próprio Domain Admins — o caminho comum para essa técnica precisa de ambos: direito de adicionar brevemente a conta-alvo a Domain Admins e direito de escrever seuprimaryGroupID. Qualquer um dos dois delegado abaixo das OUs de administração integradas já é, por si só, um achado.
Como a EtcSec detecta isso
A verificação PRIMARYGROUPID_SPOOFING da EtcSec executa, como um controle contínuo, o mesmo tipo de varredura: cada auditoria compara a primaryGroupID de cada conta com seu padrão esperado e sinaliza contas cujo grupo primário difere sem um motivo documentado, fechando exatamente a lacuna que uma exportação baseada apenas no atributo member deixa aberta. Os achados aparecem junto com a revisão de permissão de escrita (ACL_WRITE_PROPERTY_EXTENDED), que mostra quem poderia fazer a alteração em primeiro lugar, e junto com o monitoramento de grupos privilegiados (PRIVILEGED_GROUP_MEMBER_CHANGES), para que você veja, lado a lado, quais caminhos de escalonamento de privilégio o seu alerta baseado no atributo member realmente cobre.
Explore as paginas de identidade que sustentam este tema
