Netwrix 1Secure oferece visibilidade unificada de dados e identidade — gratuito por 14 dias com acesso completo.Comece um teste gratuito

Centro de recursosBlog
Controlos LDAP estendidos potentes: Anti-remediação e reconhecimento invisível no AD

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:

  1. FORCE_UPDATE → vencer conflitos de replicação (anti-remediação). Uma modificação LDAP sem efeito MODIFY que carrega LDAP_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 de WriteProperty; sem DA, sem direitos de replicação, sem DC malicioso.
  2. OBJECT_SECURITY DirSync → enumeração em massa invisível. DirSync (.841) com a OBJECT_SECURITY flag é 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:

  1. Quem tiver o número de versão mais alto vence. Cada campo lembra quantas vezes foi alterado e essa contagem é sua "versão."
  2. Somente se as versões empatarem, o AD verifica quem editou mais recentemente (carimbo de data/hora).
  3. 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 é:

  1. Versão - um contador por atributo incrementado a cada gravação de origem.
  2. Carimbo de data/hora - usado apenas se as versões forem iguais.
  3. 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

  1. Escolha um atributo de destino que o principal já pode escrever (um WriteProperty ACE).
  2. Defina o valor malicioso em DC-A.
  3. 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.
  4. 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.)
  5. 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 DrsReplicaAdd / GetNCChanges

One authenticated LDAP MODIFY + a request control

Privilege required

DA/EA (or DS-Install-Replica + topology rights) + SYSTEM

WriteProperty on the single target attribute

Server-side footprint

Config-partition objects, a transient rogue DC, cleanup

A single MODIFY to a live DC

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=0 usa 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 (flag 0x1) é 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 (ou repadmin /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ção versã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 .1974 OID 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 WriteProperty em 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 privilegiado member, 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

red/

offensive CLI (ldapctl)

Python 3 / ldap3

Collect the directory invisibly, make a change survive remediation, and probe existence without logging

blue/

defensive module (AdLdapDefense)

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

collect

Bulk-reads objects, attributes, and group member lists over the replication path as an ordinary Domain User, paging on the DirSync cookie for incremental delta runs. Scopes to what the account can already read: it does not bypass confidential attributes and does not return security descriptors (that path stays empty).

OBJECT_SECURITY DirSync

None in host logs: 0× Event 1644, 0× Event 4662. Caught only by a SACL read canary.

pin

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.

recon

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

Invoke-LdapLoggingAudit

Reports whether Event 1644 is effective: it's silently useless when the search thresholds are 0 (disabled), a common misconfig. Also reports which controls actually land in the 1644 controls field (with -Probe) and whether 4662 auditing is on. -Fix corrects the threshold trap.

LDAP logging blind spots

Invoke-ReplMetadataHunt

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

Deploy-SaclCanary / Test-SaclCanary

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

Get-ReplicationAbuse

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 (Get-Changes) as well as DCSync (Get-Changes-All). Rules that watch only Get-Changes-All miss the lower-privileged DirSync path.

DirSync / DCSync Get-Changes abuse


Referências

Compartilhar em

Saiba Mais

Sobre o autor

Retrato de darryl baker

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.