Controlos LDAP estendidos potentes: Anti-remediação e reconhecimento invisível no AD
Jul 3, 2026
Realizei uma auditoria contra todos os controles estendidos LDAP do MS-ADTS. A maioria se comporta exatamente como documentado; dois se destacaram por uso potencialmente ofensivo. Ambos abusando de controles legítimos, mas nenhum é uma escalada de privilégios:
- FORCE_UPDATE → vencer conflitos de replicação (anti-remediação). Uma modificação LDAP sem efeito
MODIFYque carregaLDAP_SERVER_FORCE_UPDATE(.1974) infla a versão de replicação por atributo sem alterar o valor do atributo. O AD resolve conflitos primeiro pela versão (timestamp apenas como critério de desempate), então um atacante que pode escrever em pelo menos um atributo pode fazer seu valor superar a correção posterior desse atributo por um defensor em outro DC. A correção reverte silenciosamente. Precisa apenas deWriteProperty; sem DA, sem direitos de replicação, sem DC malicioso. - OBJECT_SECURITY DirSync → enumeração em massa invisível. DirSync (
.841) com aOBJECT_SECURITYflag é o caminho não privilegiado: qualquer Usuário de Domínio pode ler em massa tudo que já tem permissão para ler, incluindo descritores de segurança, e não registra nada (nenhum Evento 1644, nenhum Evento 4662). Um primitivo de coleta de baixo ruído.
O tema unificador: um controle LDAP documentado, usado conforme previsto no nível do mecanismo, produz um efeito que a telemetria da Microsoft e a maioria dos defensores não esperam.
Demonstrado num laboratório de dois DC cloud.lab (Windows Server 2022, nível funcional de floresta 2016). Apenas em contexto de laboratório e investigação autorizada.
Constatação 1 - FORCE_UPDATE: Conflitos de replicação vencedores a partir de uma única gravação LDAP
A ideia em linguagem simples
Se você já conhece a replicação do AD perfeitamente, pode pular para frente. Caso contrário, aqui está uma analogia.
Imagine uma empresa com dois arquivos idênticos em dois escritórios diferentes. Estes são os dois controladores de domínio (DCs). Para manter a sincronização, toda alteração feita em um é copiada para o outro. Essa cópia é a replicação.
E se duas pessoas editarem o mesmo arquivo ao mesmo tempo em escritórios diferentes, antes que a cópia seja atualizada? Os armários discordam, e o AD precisa de uma regra para decidir quem vence:
- Quem tiver o número de versão mais alto vence. Cada campo lembra quantas vezes foi alterado e essa contagem é sua "versão."
- Somente se as versões empatarem, o AD verifica quem editou mais recentemente (carimbo de data/hora).
- Se isso também empatar, o desempate é feito pelo ID do armário.
O truque: normalmente, se você “editar” um campo reescrevendo o valor exato que ele já tinha, o AD dá de ombros, diz “nada mudou” e a versão permanece a mesma. FORCE_UPDATE é uma flag que diz “conte isso como uma mudança real mesmo assim.” Então você pode escrever Bob sobre um campo que já diz Bob seis vezes, e a versão sobe para 6 mesmo que o valor nunca tenha mudado.
Então um invasor faz uma alteração maliciosa em um campo que pode editar, aplica FORCE_UPDATE algumas vezes para aumentar a versão para 6 e espera. Quando um defensor corrige no outro gabinete (qualquer outro DC), é uma edição nova e posterior, mas a primeira alteração lá, então a versão é 1. Os gabinetes sincronizam, o AD compara 6 vs 1, e 6 vence: o valor do invasor volta e a correção do defensor desaparece silenciosamente. O invasor forçou uma alteração que supera uma mais nova e legítima.
Duas advertências honestas: funciona apenas em campos que você já poderia editar (é persistência, não escalonamento), e não é invisível. Deixa um campo cuja versão pulou sem alteração de valor. A parte realmente nova é o “preço de entrada”: o famoso ataque DCShadow faz o mesmo movimento “minha versão vence” mas precisa de poderes quase divinos de domínio (fingindo ser um DC); isso precisa de uma escrita comum e permissão em um campo.
Contexto: Como o AD decide quem vence
Active Directory é multi-master, o que significa que cada DC gravável aceita alterações que se replicam para fora. Dois DCs podem ser instruídos a alterar o mesmo atributo do mesmo objeto antes que a replicação seja reconciliada. Para um conflito por atributo a ordem de desempate é:
- Versão - um contador por atributo incrementado a cada gravação de origem.
- Carimbo de data/hora - usado apenas se as versões forem iguais.
- Server (DSA) GUID - usado apenas se a versão e estiverem empatados no timestamp.
Esses metadados são por atributo, visíveis via repadmin /showobjmeta ou msDS-replAttributeMetaData. A propriedade crucial: uma versão inferior sempre perde para uma versão superior, não importa o quão mais nova ela seja. E um MODIFY que escreve o valor existente de um atributo normalmente não faz nada (AD não incrementa a versão). Normalmente, você não pode aumentar a versão reescrevendo o mesmo valor.
O controle: LDAP_SERVER_FORCE_UPDATE (1.2.840.113556.1.4.1974)
FORCE_UPDATE é um controle documentado e benigno por enquadramento: segundo MS-ADTS, ele instrui o DC a processar a modificação mesmo quando seria uma operação sem efeito (“atualizar mesmo se os novos dados forem idênticos”). A biblioteca Java ldaptive fornece um ForceUpdateControl que faz exatamente isso, sem enquadramento de ataque. O efeito colateral importante: porque a escrita forçada conta como uma escrita originária real, incrementa a versão por atributo sem alteração de valor. Essa é a ponte. O carimbo de versão é convencionalmente considerado inacessível para um cliente LDAP (por isso o DCShadow o manipula pelo protocolo de replicação como um DC malicioso); FORCE_UPDATE o torna acessível a partir de uma MODIFICAÇÃO LDAP.
A técnica
- Escolha um atributo de destino que o principal já pode escrever (um
WritePropertyACE). - Defina o valor malicioso em DC-A.
- Inflar a versão: enviar N
MODIFYs adicionais com o mesmo valor, cada um com FORCE_UPDATE, cada um aumentando a versão sem alteração visível. - Espere: Um defensor corrige o valor, naturalmente no DC ao qual está conectado (DC-B). Sua única correção incrementa a versão em um (para atual+1). Enquanto o atacante inflacionou acima disso, o atacante ainda tem classificação superior. (No laboratório, o defensor chegou à versão 1 apenas porque o atributo não estava definido anteriormente; em geral, o atacante só precisa superar a versão da correção, o que é gratuito.)
- Convergência: O AD compara versões; a versão inflada do atacante supera a correção posterior, porém menor, do defensor. O valor do atacante vence em ambos os DCs.
O defensor vê que sua alteração “não permanece”: ele corrige, parece corrigido e minutos depois reverte.
Modelo de privilégios vs DCShadow: A parte nova
DCShadow | This technique (FORCE_UPDATE conflict-win) |
|
|---|---|---|
|
Manipulates per-attribute version |
Yes |
Yes |
|
Mechanism |
Register a rogue DC, push via DRSUAPI |
One authenticated |
|
Privilege required |
DA/EA (or |
|
|
Server-side footprint |
Config-partition objects, a transient rogue DC, cleanup |
A single |
|
Tooling |
DCShadow-class tooling |
Any LDAP client that can attach a control |
A percepção não óbvia: LDAP pode alcançar o carimbo de versão por atributo. FORCE_UPDATE quebra silenciosamente a suposição de "você deve falar o protocolo de replicação como um DC" da superfície do cliente.
Demonstração (laboratório de dois DC)
Atacante = svc-research, um usuário de domínio simples delegado apenas WP;descrição (sem direitos de replicação). As ações do atacante são executadas sob sua própria ligação NTLM; o contexto de administrador é usado puramente para a orquestração do laboratório (delegação, pausa/retomada da replicação, simulação do defensor).
Step 1 — low-priv writer bumps the version:
baseline: description version 1
attacker no-op FORCE_UPDATE -> description version 2 (no value change)
Step 2 — stage and win the conflict (replication paused):
DC01: description='ATTACKER-OWNED' version 6 @ 19:58:34 (attacker, FORCE_UPDATE x3)
DC-02: description='defender-remediation-LATER' version 1 @ 19:58:36 (defender, LATER, lower version)
=> CONVERGED: DC01 = DC-02 = 'ATTACKER-OWNED' (defender's later fix reverted)
O ingrediente ofensivo completo é um MODIFY com o controle anexado:
var m = new ModifyRequest(dn, DirectoryAttributeOperation.Replace, "description", value);
m.Controls.Add(new DirectoryControl("1.2.840.113556.1.4.1974", null, true, true)); // FORCE_UPDATE, critical
connection.SendRequest(m); // same-value write now bumps the per-attribute version
Impacto, escopo e limitações
Um primitivo anti-remediação / persistência: tornar um valor do atacante teimoso contra limpeza para qualquer atributo que o atacante já possa escrever, por exemplo msDS-AllowedToActOnBehalfOfOtherIdentity (backdoor RBCD), servicePrincipalName (reafirmar um alvo Kerberoast), scriptPath / gPLink (ponto de apoio persistente).
- Limite do escopo (testado): linked atributos (
member/memberOf) não são afetados. Eles se replicam via Linked-Value Replication com metadados por valor; uma readição FORCE_UPDATE sem efeito de um membro existente tem sucesso, mas não incrementa a versão do valor do link. Portanto, a associação ao grupo não pode ser fixada dessa forma, apenas atributos não vinculados de valor único e múltiplo. - Requer acesso de gravação existente (não escalonamento), e o defensor deve corrigir em um DC diferente (ou pré-convergência) para que o conflito exista.
- Não furtivo: deixa um salto anormal de versão sem alteração de valor, e um valor que “volta” após a remediação (harmj0y, Hunting With AD Replication Metadata, 2017).
Novidade: Uma revisão prévia de arte com múltiplas varreduras, além de uma busca autenticada de código nativo GitHub (~1.000+ resultados OID) não encontrou publicação deste primitivo específico. Quase todos os resultados são inertes (cabeçalhos SDK, bindings de linguagem, dissectors, dumps CTF supportedControl). Os vizinhos mais próximos são DCShadow (mesmo efeito, DA/EA via um DC malicioso), LDAPAngel/RIFM (uma ferramenta de recuperação de floresta que envia FORCE_UPDATE, mas não criticamente para seu propósito operacional FSMO/GC, não para inflação de versão), o benigno ForceUpdateControl do ldaptive, e a corrida de "Objetos em Conflito" a nível de objeto da Tenable. Nenhum deles usa esta técnica. A ausência de evidência não é prova, mas a vitória no conflito / a aplicação anti-remediação parece não publicada.
Constatação 2 - OBJECT_SECURITY DirSync: Enumerando Active Directory sem trilha de log
A ideia em linguagem simples
Um usuário comum já pode consultar a maioria das coisas no Active Directory: nomes, associações a grupos, até mesmo as listas de permissões (ACLs) em objetos que ele pode ler. Normalmente, essas consultas podem ser registradas pelo log de consultas do DC. DirSync é um recurso de sincronização destinado a ferramentas como Entra Connect para puxar alterações. Uma de suas opções, OBJECT_SECURITY, permite que um usuário comum a execute para ler tudo do Active Directory que ele já tem permissão para ler, mas porque ela utiliza a replicação em vez do caminho normal de pesquisa, o DC não registra nada. São os mesmos dados que um usuário já poderia coletar, mas sem deixar rastros. Este método também fornece um "marcador" (cookie) para voltar depois apenas pelo que mudou no AD.
O mecanismo
DirSync (LDAP_SERVER_DIRSYNC_OID, .841) tem dois modos:
flags=0usa semântica completa de replicação e requer o direito de replicação Get-Changes. Este é o caminho privilegiado, adjacente ao DCSync, e ele é registrado via Evento 4662.OBJECT_SECURITY(flag0x1) é o caminho não privilegiado documentado para chamadores comuns: requer nenhum direito de replicação e nenhuma alteração de permissão, apenas Domain Users, e limita os resultados aos dados que o chamador já pode ler. (Este é o caminho que Simon Décosse, simondotsh, documentou em 2022. Minha contribuição é a consequência validada da detecção.)
Porque OBJECT_SECURITY exerce no Get-Changes right, produz no Event 4662; e porque DirSync usa o replication code path rather than the search path, produz no Event 1644. Cai completamente entre as duas fontes de log do host.
O cookie DirSync que ele retorna também permite que você reconecte mais tarde e puxe apenas as alterações desde a última vez, funcionando também como um monitor de mudanças de baixo ruído.
Por que é uma oportunidade sorrateira
É uma oportunidade genuína para a fase de reconhecimento / enumeração:
- Sem acesso especial: Qualquer conta de domínio comprometida funciona. Não há direito de replicação para solicitar, nenhuma alteração em schema/searchFlags, nada que por si só pareça suspeito.
- Sem pegada: Coleta em massa de objetos e membros com trilha de log sem custo, além de uma sincronização delta integrada para monitoramento contínuo.
Isto é furtivo, não um novo acesso. Não fornece a um atacante dados que ele não poderia ler de outra forma. Ele se limita ao acesso de leitura efetivo, retornando exatamente o que uma busca LDAP comum retornaria. Crucialmente, ele não contorna o portão de atributo confidencial (searchFlags 0x80): um atributo confidencial é retornado somente se o chamador tiver direito genuíno de lê-lo (possui o direito CONTROL_ACCESS). Essa contorna pertence ao outro modo DirSync, flags=0, que usa semântica de replicação para vazar atributos confidenciais para qualquer pessoa com o direito Get-Changes (assunto do post complementar sobre pontos cegos de detecção). OBJECT_SECURITY também não pode ler segredos (não é DCSync, então nenhum material de senha). O que muda é puramente a evasão: uma varredura comum de SD_FLAGS deixaria registros do Evento 1644 onde quer que o registro de consultas LDAP esteja ativado; a versão DirSync de OBJECT_SECURITY não deixa nenhum em nenhum registro. O valor para um atacante é uma coleta de baixo ruído que derrota a telemetria de busca LDAP na qual os defensores confiam, por isso vale a pena saber sobre isso mesmo que não conceda nenhum novo privilégio.
Detecção e defesa
Ambas as descobertas compartilham um tema: a óbvia ideia de detecção não funciona, e os logs do host são mais cegos do que os defensores supõem. Tudo abaixo foi validado ao executar as técnicas no laboratório.
FORCE_UPDATE (Constatação 1)
- Primário - busca de metadados de replicação: Instantâneo
msDS-replAttributeMetaData(ourepadmin /showobjmeta) para atributos sensíveis e alerta quando uma versão por atributo aumenta enquanto o hash do valor permanece inalterado. No laboratório, isso sinalizou claramente o ataque (descriçãoversão 28 → 29, valor inalterado). Um segundo sintoma: um valor que reaparece após a remediação. - O evento 1644 é cego para isso: FORCE_UPDATE utiliza um
MODIFY; o evento 1644 registra apenas pesquisas, então o modify não produz nenhum evento 1644. Portanto, uma regra baseada no.1974OID nos logs de consulta nunca dispara. A detecção por fio precisa de PCAP/ETW, e o controle requer um signed bind (um simple/Basic bind é rejeitado), limitando a visibilidade cleartext-389. - Endurecimento: Minimize
WritePropertyem atributos sensíveis (o pré-requisito completo); corrija no mesmo DC (quando possível) e verifique a versão depois.
OBJECT_SECURITY DirSync (Constatação 2)
- Os logs do host não vão ver isso: Sem 4662 (sem direito Get-Changes) e sem 1644 (caminho de replicação), então não há regra de evento para escrever; este é o ponto cego.
- O que realmente funciona é limitado: A captura realista é network / ETW capture do controle DirSync na rede (sujeito a LDAPS) mais estabelecimento da linha de base do uso do DirSync e alerta sobre isso a partir de qualquer fonte não sincronizada. Um SACL read-canary não é confiável um respaldo confiável aqui: em testes, um ACE de auditoria ReadProperty não gerou o Evento 4662 para uma leitura comum do atributo. A auditoria de leitura do host do AD não é confiável, e a leitura do caminho de replicação do DirSync não muda isso. (Canários SACL são confiáveis contra a atualização FORCE_UPDATE write e contra os direitos de replicação DirSync/DCSync, apenas não contra essa leitura furtiva.)
- Observe também o ângulo do ADWS: Os cmdlets PowerShell AD (Get-ADUser e amigos) não falam LDAP diretamente. Em vez disso, eles passam pelo Active Directory Web Services (ADWS, TCP 9389), que retransmite a consulta para o DC localmente. Portanto, o Evento 1644 registra o cliente como 127.0.0.1 (o próprio DC), não o endereço real do operador.
- Por que isso importa: Cada regra 1644 deve excluir 127.0.0.1. Porque as próprias buscas internas do DC geram ruído constante de loopback, essa mesma exclusão também elimina qualquer atividade que um invasor proxy através do ADWS. Apenas a visibilidade de rede/ETW vê a fonte verdadeira.
Canários SACL: o que são e onde ajudam
Várias recomendações acima baseiam-se em canários SACL, então vamos falar sobre eles. O descritor de segurança de cada objeto AD possui duas listas de controle de acesso:
- DACL: decide quem pode fazer o quê (permissões)
- SACL: (System ACL) decide o que é auditado
Um ACE de auditoria SACL diz “quando este objeto ou atributo é acessado, emitir o Evento de Segurança do Windows Event 4662.” Um canary é um tripwire colocado deliberadamente no estilo “honeytoken” em um objeto de alto valor que a atividade legítima raramente toca, então qualquer acesso o ativa. Como é avaliado na camada de acesso ao objeto (não na camada de controle ou log), dispara independentemente de qual controle ou transporte LDAP foi usado.
Para implantar:
- Ative Audit Directory Service Access (Sucesso) e adicione um ACE de auditoria para o acesso que você considera importante em suas joias da coroa (por exemplo, o atributo RBCD
msDS-AllowedToActOnBehalfOfOtherIdentity, membro do grupo privilegiadomember,AdminSDHolder).
A pegadinha: forte para gravações, fraco para leituras (validado).
Essas duas descobertas falham em diferentes defesas, então o canário ajuda de forma desigual:
- FORCE_UPDATE é um write: um SACL write-canary no atributo alvo que dispara de forma confiável o evento 4662 na modificação maliciosa e a busca de metadados de replicação o detecta independentemente. (Uma auditoria SACL em um controle de access right também detecta de forma confiável os direitos de replicação DirSync/DCSync via Get-Changes 4662.)
- OBJECT_SECURITY DirSync é uma leitura: A auditoria de leitura do host do AD não é confiável. Em meus testes, um ACE de auditoria ReadProperty não gerou o evento 4662 nem mesmo para uma leitura comum do atributo. Portanto, um canário SACL não detecta de forma confiável essa leitura furtiva. Em vez disso, depende da captura de rede/ETW e do baselining do DirSync.
A versão direta: audit canaries são seu melhor alarme para o lado de gravação e abuso de direitos de replicação, mas a furtiva leitura precisa de olhos no fio.
Ferramentas
Criei duas ferramentas de prova de conceito para Red Team e Blue Team explorarem e defenderem os controles estendidos do LDAP: LDAP Extended Controls Toolkit.
Folder | Tool | Language | Use it to |
|---|---|---|---|
|
offensive CLI ( |
Python 3 / ldap3 |
Collect the directory invisibly, make a change survive remediation, and probe existence without logging |
|
|
defensive module ( |
PowerShell |
Audit what your DC actually logs, hunt replication-metadata tampering, deploy and self-test SACL canaries, and catch replication (DirSync/DCSync) abuse |
O que cada ferramenta faz
red/ — ldapctl (ofensivo)
Três subcomandos, cada um operacionalizando uma técnica validada de controle estendido. Flags completas, privilégios e formatos de saída estão em red/README.md.
Subcommand | What it actually does | Control / finding | Footprint |
|---|---|---|---|
|
|
Bulk-reads objects, attributes, and group |
OBJECT_SECURITY DirSync |
None in host logs: 0× Event 1644, 0× Event 4662. Caught only by a SACL read canary. |
|
|
Writes a value, then inflates that attribute's per-attribute replication version so it wins AD conflict resolution (version beats timestamp) against a defender's later correction on another DC. Refuses linked attributes (LVR, unaffected). Needs only WriteProperty on the attribute. |
FORCE_UPDATE conflict-win |
Not stealthy: writes the value and bumps its version. Persistence/anti-remediation, not privesc. |
|
|
Tests whether a specific DN exists at base scope without reading its attributes and without appearing in Event 1644. Base-DN oracle only (AD evaluates the control as 0 under subtree scope). |
EXPECTED_ENTRY_COUNT oracle |
Invisible to Event 1644: the control isn't recorded in the 1644 controls field. |
azul/ — AdLdapDefense (defensivo)
Um módulo PowerShell com cinco funções exportadas cobrindo quatro capacidades de detecção/endurecimento. Parâmetros e saída de exemplo estão em blue/README.md. Requer PowerShell 5.1+ e RSAT (ActiveDirectory), executado a partir de uma estação de trabalho administrativa que possa alcançar o DC.
Function | What it actually does | Catches |
|---|---|---|
|
|
Reports whether Event 1644 is effective: it's silently useless when the search thresholds are |
LDAP logging blind spots |
|
|
Baselines each sensitive attribute's replication Version plus a value hash, then on later runs flags any object where the version rose while the value did not change. That mismatch is the tamper signature, and it's the reliable catch because FORCE_UPDATE rides a modify and leaves no 1644. |
FORCE_UPDATE / DCShadow-class version tampering |
|
|
Plants a SACL audit ACE on a high-value object so access raises Event 4662, then self-tests that it fires. A read canary is the reliable catch for the OBJECT_SECURITY DirSync collection that is otherwise invisible (matched by objectGUID, not CN). |
Reads (including invisible DirSync) and writes |
|
|
Hunts Event 4662 carrying a Get-Changes replication GUID from a non-DC, non-approved-sync account, and recovers the source IP by joining to the matching 4624 logon on LogonId. Flags DirSync ( |
DirSync / DCSync Get-Changes abuse |
Referências
- MS-ADTS,
LDAP_SERVER_FORCE_UPDATE_OID.https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/3c5e87db-4728-4f29-b164-01dd7d7391ea - MS-ADTS / MS-DRSR. Resolução de conflitos de replicação (versão → timestamp → DSA GUID); DirSync (
LDAP_SERVER_DIRSYNC_OID) e semântica de replicação - DCShadow, Delpy & Le Toux, BlueHat IL 2018. https://www.dcshadow.com/
- harmj0y, Caça com metadados de replicação do Active Directory (2017). https://blog.harmj0y.net/defense/hunting-with-active-directory-replication-metadata/
- simondotsh, Entendendo e abusando do DirSync (2022). https://simondotsh.com/infosec/2022/07/11/dirsync.html
- Tenable, Uso de objetos conflitantes no Active Directory para obter privilégios (2024). https://medium.com/tenable-techblog/using-conflicting-objects-in-active-directory-to-gain-privileges-243ef6a27928
Compartilhar em
Saiba Mais
Sobre o autor
Darryl Baker
Pesquisador Sênior de Segurança
Darryl G. Baker é um Pesquisador Sênior de Segurança na Netwrix e uma autoridade reconhecida em segurança de Identity e Active Directory. Com mais de uma década de experiência em sistemas de identidade, ele liderou avaliações de segurança empresarial, treinamentos em segurança de identidade e emulações de ameaças focadas em Active Directory, Entra ID e ambientes Azure. Darryl ministrou treinamentos e demonstrações altamente avaliados no BlueTeamCon, BSidesCT, The Experts Conference e Wild Wild West Hackin’ Fest. Ele é o arquiteto por trás de inúmeros laboratórios práticos de emulação de ataques — aproveitando as ferramentas atuais de red team e blue team para ajudar os defensores a dominar desde a análise de caminhos de ataque até a caça a ameaças. Em suas sessões, Darryl combina profundo conhecimento técnico com estudos de caso do mundo real, capacitando profissionais do blue team a fortalecer sua postura de segurança de identidade e defender-se contra técnicas adversárias em evolução.
Saiba mais sobre este assunto
Alternativas ao ManageEngine: Ferramentas de AD Management e Segurança
Criar usuários do AD em massa e enviar suas credenciais por e-mail usando PowerShell
Como criar, alterar e testar senhas usando PowerShell
Como adicionar e remover grupos AD e objetos nos grupos com PowerShell
Confianças no Active Directory