Netwrix 1Secure는 데이터와 아이덴티티 전반에 걸쳐 통합된 가시성을 제공합니다 - 14일간 무료로 전체 액세스가 가능합니다.무료 평가판 시작

리소스 센터블로그

강력한 LDAP 확장 제어: AD에서의 자동 복구 무력화와 보이지 않는 정찰

강력한 LDAP 확장 제어: AD에서의 자동 복구 무력화와 보이지 않는 정찰

Jul 3, 2026

모든 MS-ADTS LDAP 확장 컨트롤에 대해 감사를 실행했습니다. 대부분은 문서대로 정확히 동작했지만, 두 가지가 공격적으로 악용될 가능성 때문에 눈에 띄었습니다. 둘 다 정상적인 컨트롤을 남용하지만, 둘 다 권한 상승은 아닙니다:

  1. FORCE_UPDATE → 복제 충돌에서 승리(anti-remediation). 값이 바뀌지 않는 no-op LDAP MODIFYLDAP_SERVER_FORCE_UPDATE (.1974) 는 해당 특성의 값은 변경하지 않으면서 특성별 복제 버전만 부풀립니다. AD는 충돌을 버전부터 먼저 판단해 해결하며(동률일 때만 타임스탬프를 사용), 최소 하나의 특성에 쓸 수 있는 공격자 는 다른 DC에서 방어자가 그 특성을 나중에 수정하더라도 자신의 값이 그 수정값을 이기게 만들 수 있습니다. 수정은 조용히 되돌아갑니다. 필요한 권한은 WriteProperty 하나뿐입니다. DA도 필요 없고, 복제 권한도 없고, 악성(rogue) DC도 필요 없습니다.
  2. OBJECT_SECURITY DirSync → 보이지 않는 대량 열거(invisible bulk enumeration). DirSync (.841)에서 OBJECT_SECURITY 플래그를 사용하면 비권한 경로(unprivileged path)가 됩니다. 즉, 어떤 Domain User든 보안 디스크립터를 포함해 이미 읽을 수 있도록 허용된 모든 것을 일괄로 읽을 수 있으며, 아무것도 기록하지 않습니다(이벤트 1644도 없음, 이벤트 4662도 없음). 소음이 적은 수집용 기본 구성요소(primitive)입니다.

통합적인 핵심: 문서화된 LDAP 제어를 메커니즘 수준에서 의도된 대로 사용하면, Microsoft의 텔емetry와 대부분의 방어자들이 예상하지 못하는 효과가 발생합니다.

두 대의 DC 환경 cloud.lab (Windows Server 2022, 포리스트 기능 수준 2016)에서 시연했습니다. 실험실/권한이 있는 연구 맥락에서만 사용.

사례 1 - FORCE_UPDATE: 단 한 번의 LDAP 쓰기로 복제 충돌을 승리로 이끌기

쉽게 말해 정리하면

AD 복제를 이미 완전히 알고 있다면 바로 다음으로 건너뛰세요. 그렇지 않다면 비유로 설명해 드릴게요.

서로 다른 두 사무실에 똑같은 서류 보관함 두 개가 있는 회사를 떠올려 보세요. 이 보관함이 바로 두 개의 도메인 컨트롤러(DC)입니다. 동기화를 유지하려면 한쪽에서 발생한 모든 변경 사항이 다른 쪽에 그대로 복사됩니다. 이 복사가 바로 replication(복제)입니다.

만약 두 사람이 서로 다른 사무실에서 같은 파일동시에 복사가 따라잡기 전에 편집한다면 어떻게 될까요? 보관함의 내용이 서로 달라지고, AD는 승자가 누구인지 결정할 규칙이 필요합니다:

  1. 버전 번호가 더 높은 쪽이 승리합니다. 모든 필드는 몇 번이나 변경되었는지 기억하며, 그 횟수가 바로 해당 필드의 "version(버전)"입니다.
  2. 버전이 같을 때만 AD는 누가 가장 최근에 편집했는지(타임스탬프)를 확인합니다.
  3. 그래도 동점이면 캐비닛의 ID로 동점을 가릅니다.

요령: 보통은 필드를 다시 쓰기로 “수정”할 때, 이미 가지고 있던 정확히 동일한 값을 그대로 기록하면 AD는 아무 일도 없었다며 “변경 사항 없음”이라고 하고 버전은 그대로 유지됩니다. FORCE_UPDATE 는 “어쨌든 이걸 실제 변경으로 쳐줘.” 라는 의미의 플래그입니다. 그래서Bob 이 이미Bob 라고 적혀 있는 필드에 6번 쓰면 값은 한 번도 바뀌지 않았는데도 버전이 6까지 올라갑니다.

따라서 공격자는 자신이 편집할 수 있는 필드에 악의적인 변경을 한 번 가한 뒤 FORCE_UPDATE를 몇 번 적용해서 버전을 6으로 올리고 기다립니다. 방어자가 이를 다른 캐비닛(다른 모든 DC)에서 수정하면, 이는 그보다 나중에 해당 캐비닛에서 최초로 일어난 변경이므로 버전은1입니다. 캐비닛들이 동기화되면 AD가 6 대 1을 비교하고 6이 이깁니다: 공격자의 값이 다시 나타나고 방어자의 수정은 조용히 사라집니다. 공격자는 더 최신의 정당한 변경을 누르는 방식으로 강제 변경을 만들어 낸 것입니다.

두 가지 솔직한 함정: 이건 이미 편집할 수 있던 필드에만 적용됩니다. (이건 권한을 계속 유지하는 것이지, 권한 상승(escalation)이 아닙니다) 그리고 보이지도 않습니다. 값은 바뀌지 않았는데 버전만 점프한 필드를 남깁니다. 정말 새로운 부분은 “참가 비용 입니다. 유명한 DCShadow 공격은 똑같이 “내 버전이 이긴다”는 수를 쓰지만, 도메인 거의 신급의 권한이 필요합니다(DC인 척하려면 be DC); 반면 이것은 일반적인 쓰기 1번과 하나의 필드에 대한 권한만 필요합니다.

배경: AD가 승자를 결정하는 방법

Active Directory는 multi-master입니다. 즉, 모든 쓰기 가능한 DC는 변경 사항을 수용하며, 그 변경 사항은 바깥으로 복제됩니다. 복제가 조정하기 전에 두 DC에 동일 객체의 같은 속성을 변경하라고 지시할 수 있습니다. 속성별(per-attribute) 충돌이 발생하면 tiebreak(우선순위) 순서는 다음과 같습니다:

  1. 버전: 각 원본 쓰기(변경)를 수행할 때 속성별 카운터가 1씩 증가합니다.
  2. 타임스탬프: 버전이 동일한 경우에만 사용됩니다.
  3. 서버(DSA) GUID: 버전 타임스탬프가 동률인 경우에만 사용됩니다.

이 메타데이터는 속성별이며 다음을 통해 확인할 수 있습니다: repadmin /showobjmeta 또는 msDS-replAttributeMetaData. 핵심 속성은 다음과 같습니다: 더 낮은 버전은 아무리 더 최신처럼 보이더라도 항상 더 높은 버전에 패합니다. 그리고 MODIFY 로 인해 속성의 기존 값이 다시 기록되면 일반적으로 no-op입니다(AD는 버전을 증가시키지 않습니다). 보통 동일한 값을 다시 써서 버전을 올릴 수 없습니다.

제어(컨트롤): LDAP_SERVER_FORCE_UPDATE (1.2.840.113556.1.4.1974)

FORCE_UPDATE는 문서화된(정상적인 사용 목적의) 프레이밍 기반 제어입니다. MS-ADTS에 따르면, 이는 DC가 수정이 원래라면 무의미한 no-op가 되어버릴 상황에서도 해당 변경을 처리하도록 지시합니다 (“새 데이터가 동일하더라도 업데이트”). Java 라이브러리 ldaptive에는 ForceUpdateControl가 정확히 이 작업을 수행하도록 포함되어 있으며, 공격용 프레이밍은 전혀 없습니다. 중요한 부작용은 다음과 같습니다. 강제 쓰기는 실제로 ‘기원(originating)’이 있는 쓰기로 집계되기 때문에, 값이 바뀌지 않더라도 특성(어트리뷰트)별 버전을 증가시킵니다. 이것이 바로 연결 고리(브리지)입니다. 버전 스탬프는 관례적으로 LDAP 클라이언트가 도달할 수 없는 것으로 간주됩니다(그래서 DCShadow는 이를 ‘악성 DC(rogue DC)’로서 복제 프로토콜을 통해 조작합니다). FORCE_UPDATE는 일반적인 인증된 LDAP MODIFY에서 그에 접근 가능하게 만듭니다.

기술(테크닉)

  1. 대상 특성(attribute)을 선택합니다. 즉, 주체(principal)가 이미 쓸 수 있어야 합니다(1 WriteProperty ACE).
  2. 악성 값을 설정합니다 DC-A에서.
  3. 버전을 부풀리기: 동일한 값의 N개를 추가로 전송 MODIFY 하되, 각각 FORCE_UPDATE를 사용하고, 각각 버전만 올리며 눈에 보이는 변경은 없게 합니다.
  4. 잠깐: 방어자가 값을 수정합니다. 이는 자신이 연결된 어느 DC에서든 자연스럽게 수행되며 (DC-B), 방어자의 단 한 번의 수정은 버전을 1 증가시킵니다 ( current+1 ). 공격자가 그보다 위로 부풀려 놓기만 하면, 공격자가 여전히 더 높은(우선) 순위를 갖습니다. (실험실에서는 해당 속성이 이전에 설정되지 않았던 탓에 방어자가 버전 1에 도착했지만, 일반적으로는 공격자가 수정값의 버전을 더 높이기만 하면 됩니다. 이는 무료입니다.)
  5. 수렴: AD는 버전을 비교합니다. 공격자가 부풀린 버전이, 방어자가 나중에 수정했지만 더 낮은 버전인 수정값보다 우선합니다. 공격자의 값은 두 DC 모두에서 승리합니다.

방어자는 변경이 “달라붙지 않는다”는 것을 봅니다. 즉, 수정하면 고쳐진 것처럼 보이지만, 몇 분 뒤에 다시 되돌아갑니다.

권한 모델 vs DCShadow: 새롭게 달라진 부분

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

잘 알려지지 않은 통찰: LDAP은 애초에 속성별 버전 스탬프에까지 접근할 수 있습니다. FORCE_UPDATE는 클라이언트 관점에서 “DC로서 복제 프로토콜을 말해야 한다”는 가정을 조용히 깨뜨립니다.

데모(2대의 DC 실험 환경)

공격자 = svc-research, 일반 도메인 사용자로서 오직 WP;description (복제 권한 없음)만 위임받았습니다. 공격자 동작은 공격자 자신의 NTLM 바인드 하에서 실행되며, 관리자 컨텍스트는 실험실 오케스트레이션(위임, 복제 일시 중지/재개, 방어자 시뮬레이션)에만 사용됩니다.

      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)
      

공격의 핵심 재료는 하나 MODIFY 에 제어(control)를 붙인 것입니다:

      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
      

영향, 범위 및 한계

공격자가 이미 쓸 수 있는 어떤 특성에 대해서도 anti-remediation / persistence 원시적 기법(프리미티브): 공격자 값이 정리(정화) 작업에 대해 끈질기게 버티도록 만드는 것, 예를 들면 msDS-AllowedToActOnBehalfOfOtherIdentity (RBCD 백도어), servicePrincipalName (Kerberoast 대상 다시 주장), scriptPath / gPLink (끈끈한 발판).

  • 범위 경계(테스트됨): 연결(Linked) 특성(member / memberOf)는 영향을 받지 않습니다. 이들은 값별(per-value) 메타데이터와 함께 Linked-Value Replication을 통해 복제됩니다. 기존 멤버를 no-op FORCE_UPDATE로 다시 추가하면 성공하지만 링크 값의 버전을 증가시키지는 않습니다. 따라서 그룹 멤버십은 이런 방식으로 고정(pinning)할 수 없고, 단일 값 또는 다중 값이지만 연결되지 않은 특성만 가능합니다.
  • 기존의 쓰기 권한이 필요합니다 (권한 상승이 아님). 또한 방어자는 충돌이 존재하려면 다른 DC (또는 수렴 이전)에 대해 수정해야 합니다.
  • 은밀하지 않습니다: 값의 변화 없이 비정상적인 버전 점프를 남기며, 복구(조치) 후에 값이 “다시 돌아옵니다”(harmj0y, Hunting With AD Replication Metadata, 2017).

새로움(참신함): 다중 스윕의 선행기술(prior-art) 검토와 인증된 GitHub 네이티브 코드 검색(약 1,000+ OID 히트)을 수행했지만, 이 특정 프리미티브(원시적 기법)의 출판물은 찾지 못했습니다. 거의 모든 히트는 무해(비활성)합니다(SDK 헤더, 언어 바인딩, 디스섹터, CTF supportedControl 덤프). 가장 가까운 이웃은 DCShadow(동일한 효과, Rogue DC를 통한 DA/EA)이고, LDAPAngel/RIFM (포리스트 복구 도구로서 sends FORCE_UPDATE를 보내지만, 버전 팽창이 아니라 운영상 FSMO/GC 목적을 위한 비핵심적인 방식이며), ldaptive의 무해한 ForceUpdateControl, 그리고 Tenable의 오브젝트 수준 "Conflicting Objects" 레이스입니다. 이들 모두 이 기법을 사용하지 않습니다. 증거의 부재는 증명이 아니지만, 충돌에서 이기는 방식 / anti-remediation application 은(는) 출판되지 않은 것으로 보입니다.

Finding 2 - OBJECT_SECURITY DirSync: 로그 흔적 없이 Active Directory를 열거

한마디로 정리하면

일반 사용자는 이미 Active Directory에서 대부분의 항목을 조회할 수 있습니다. 예를 들어 이름, 그룹 멤버십, 그리고 읽을 수 있는 개체에 대한 권한 목록(ACL)까지도 조회 가능합니다. 일반적으로 이러한 조회는 로그될 수 있으며, DC의 쿼리 로그에 기록될 수 있습니다. DirSync는 Entra Connect 같은 도구가 변경 사항을 가져오도록 하기 위한 동기화 기능입니다. 그 옵션 중 하나인 OBJECT_SECURITY를 사용하면 일반 사용자가 자신의 권한으로 이미 읽을 수 있는 Active Directory의 모든 정보를 읽기 위해 이를 실행할 수 있지만, 일반 search 경로 대신 replication 기반 배관을 타고 진행되기 때문에 DC에는 아무것도 기록되지 않습니다. 사용자가 이미 수집할 수 있었던 것과 같은 데이터이지만 흔적이 없는 형태입니다. 또한 이 방법은 AD에서 변경된 내용만 나중에 다시 가져올 수 있도록 “북마크”(쿠키)도 제공합니다.

동작 방식

DirSync (LDAP_SERVER_DIRSYNC_OID, .841)에는 두 가지 모드가 있습니다:

  • flags=0 전체 복제(Replication) 시맨틱을 사용하며 Get-Changes 복제 권한이 필요합니다. 이는 특권이 있는 DCSync에 인접한 경로이며, Event 4662를 통해 기록됩니다.
  • OBJECT_SECURITY (flag 0x1) 는 일반 호출자를 위해 문서화된 권한이 없는 경로입니다. 이 경로는 복제 권한이 필요 없고 권한 변경도 필요 없으며 Domain Users만 해당되고, 결과 범위를 호출자가 이미 읽을 수 있는 데이터로 제한합니다. (이것은 Simon Décosse, simondotsh가 2022년에 문서화한 경로입니다. 제 기여는 검증된 탐지 결과입니다.)

OBJECT_SECURITY는 Get-Changes 권한을 사용하지 않기 때문에, Event 4662가 생성되지 않습니다. 또한 DirSync는 검색 경로가 아니라 복제 코드 경로를 사용하기 때문에, Event 1644가 생성되지 않습니다. 이 경로는 두 가지 호스트 로그 소스 사이의 영역에 완전히 해당합니다.

DirSync가 반환하는 쿠키를 사용하면, 나중에 다시 연결해서 지난번 이후의 변경 사항만 가져올 수 있으므로, 잡음이 적은 변경 모니터로도 활용됩니다.

왜 이것이 교묘한 기회인지

이는 recon / enumeration 단계에 대한 진정한 기회입니다:

  • 특별한 권한 없음: 손상된 도메인 계정이라면 무엇이든 작동합니다. 요청할 복제 권한이 없고, 스키마/searchFlags 변경도 없으며, 그 자체로 의심스러워 보이는 것이 없습니다.
  • 흔적 없음: 비용 부담 없이 로그가 남지 않는 대량 개체 및 구성원 수집과, 지속 모니터링을 위한 내장 델타 동기화가 함께 제공됩니다.

이것은 새로운 접근 권한을 주는 것이 아니라, 은밀함(stealth)입니다. 공격자에게, 그렇지 않으면 읽을 수 없었던 데이터를 제공하지 않습니다. 호출자의 effective read access 범위 내에서만 결과를 반환하며, 일반적인 LDAP 검색과 정확히 동일합니다. 핵심은 이것이 기밀 특성 게이트를 우회하지 않는다는 것 입니다( searchFlags 0x80): 호출자가 진정으로 읽을 권리가 있는 경우에만 기밀 특성이 반환됩니다( CONTROL_ACCESS 권한을 보유한 경우). 이 우회는 다른 DirSync 모드인 flags=0 에 해당하며, 복제(replication) 의미론을 사용해 Get-Changes 권한을 가진 누구에게나 기밀 특성을 유출합니다(함께 제공되는 detection blind spots 게시물의 주제). 또한 OBJECT_SECURITY는 비밀 정보를 읽을 수도 없습니다(이는 DCSync가 아니라서 비밀번호 관련 자료가 없다는 의미입니다). 달라지는 것은 순전히 회피(evasion) 입니다. 즉, 일반적인 SD_FLAGS 스윕(sweep) LDAP 쿼리 로깅이 켜져 있는 곳이면 어디서든 Event 1644 기록을 남기게 됩니다. 반면 OBJECT_SECURITY DirSync 버전은 어느 로그에도 남기지 않습니다. 공격자 입장에서는 수집 시 잡음이 적어서 방어자들이 의존하는 LDAP 검색 텔레메트리를 무력화 하므로, 새로운 권한을 부여하지 않더라도 알아둘 가치가 있습니다.

탐지 및 방어

두 가지 결과에는 공통된 주제가 있습니다. 즉, 가장 명백한 탐지 아이디어는 작동하지 않으며, 호스트 로그는 방어자가 가정하는 것보다 더 눈이 멀어 있습니다. 아래 내용은 실험실에서 해당 기법을 실행해 검증한 것입니다.

FORCE_UPDATE (Finding 1)

  • 1차 - 복제 메타데이터( replication-metadata ) 추적: 스냅샷 msDS-replAttributeMetaData (또는 repadmin /showobjmeta)를 민감한 특성에 대해 확인하고, 특성별 값 해시는 그대로인데 버전만 상승하는 경우 알림을 발생시키세요. 실험실에서는 이 방법이 공격을 명확하게 식별했습니다 (description 버전 28 → 29, 값은 변경 없음). 두 번째 증상: 조치(복구) 후 값이 다시 나타나는 경우 .
  • 이것에는 Event 1644가 눈이 멉니다: FORCE_UPDATE는 MODIFY를 타고 진행합니다. Event 1644는 검색(searches)만 기록하므로, 수정(modify)은 1644 이벤트를 생성하지 않습니다. 따라서 질의 로그에서 .1974 OID를 기준으로 한 규칙은 절대 발동하지 않습니다. 와이어 탐지는 PCAP/ETW가 필요하며, 제어(control)에는 signed bind 가 필요합니다(단순/Basic bind는 거부됨). 이 때문에 cleartext-389 가시성이 제한됩니다.
  • 하드닝: 민감한 특성에 대한 WriteProperty 권한을 최소화하세요(전체 전제 조건). 가능하면 동일한 DC에서 조치(remediate)를 수행하고, 이후 버전을 확인하세요.

OBJECT_SECURITY DirSync (발견 2)

  • 호스트 로그로는 확인되지 않습니다: 4662가 없고(Get-Changes 권한 없음), 1644도 없으며(복제 경로 없음) 따라서 기록할 이벤트 규칙이 없습니다. 이것이 바로 맹점입니다.
  • 실제로 효과가 있는 것은 제한적입니다: 현실적인 대응책은 네트워크 / ETW 캡처 로 전송 구간에서 DirSync 제어를 확인하는 것(LDAPS의 영향을 받음)과 DirSync 사용에 대한 기준선 설정 그리고 동기화가 아닌 어떤 소스에서든 이를 감지해 알림을 내는 것입니다. SACL 읽기-카나리는 신뢰할 수 있는 대책이 아닙니다. 테스트에서는 ReadProperty 감사 ACE가 해당 특성의 일반적인 읽기 동작에 대해 이벤트 4662를 발생시키지 않았습니다. AD의 호스트 기반 읽기 감사는 신뢰성이 낮고, DirSync의 복제 경로 읽기는 이를 바꾸지 못합니다. (SACL 카나리는 FORCE_UPDATE 쓰기 및 복제 권한이 있는 DirSync/DCSync에 대해서는 신뢰할 수 있지만, 이처럼 은밀한 읽기에 대해서는 그렇지 않습니다.)
  • ADWS 측면도 함께 보세요: PowerShell의 AD cmdlet(Get-ADUser 및 유사 명령)은 LDAP을 직접 사용하지 않습니다. 대신 Active Directory Web Services(ADWS, TCP 9389)를 경유하며, 쿼리를 로컬에서 DC로 중계합니다. 따라서 이벤트 1644에는 연산자(운영자)의 실제 주소가 아니라 127.0.0.1(DC 자신)로 기록됩니다.
    • 왜 중요할까요: 모든 1644 규칙은 127.0.0.1을 제외해야 합니다. DC의 내부 검색이 지속적으로 루프백 노이즈를 생성하므로, 동일한 제외 조건이 공격자가 ADWS를 통해 프록시하는 모든 활동도 함께 걸러버립니다. 진짜 소스는 네트워크/ETW 가시성만이 확인할 수 있습니다.

SACL 카나리: 무엇이며 어디에 도움이 되는가

앞에서 소개한 몇 가지 권장 사항은 SACL canaries에 기대고 있으므로, 이에 대해 이야기해 보겠습니다. 모든 AD 개체의 보안 설명자(security descriptor)에는 두 가지 액세스 제어 목록(access-control lists)이 포함됩니다.

  • DACL: 무엇을 누가 할 수 있는지 (권한)
  • SACL: 어떤 것이 감사 대상이 되는지 결정합니다

SACL 감사 ACE는 “이 개체 또는 속성에 액세스하면 Windows Security Event 4662를 생성(emit)하라”라고 말합니다. 카나리는 정당한 활동이 거의 건드리지 않는 고가치 개체에 의도적으로 배치한 “honeytoken 스타일” 트립와이어(탐지용 덫)로, 어떤 액세스가 발생하든 이를 즉시 점화(트리거)합니다. 이는 제어(control)나 로그(log) 계층이 아니라 개체-액세스(object-access) 계층에서 평가되기 때문에, 사용된 어떤 LDAP 제어 또는 전송 방식이든 상관없이 작동합니다.

배포하려면:

  • Audit Directory Service Access (성공)을 활성화하고, 핵심 자산(crown jewels)에서 관심 있는 액세스에 대한 감사 ACE를 추가하세요(예: RBCD 속성 msDS-AllowedToActOnBehalfOfOtherIdentity, privileged-group member, AdminSDHolder).

주의: 쓰기에는 강하지만 읽기에는 약함(검증됨).

이 두 가지 관측 결과는 서로 다른 방어 체계를 무력화하므로 카나리는 불균등하게 도움이 됩니다:

  • FORCE_UPDATE는 write입니다: 대상 속성에 대한 SACL write-canary는 악의적인 수정에서 4662를 안정적으로 유발하고, 복제 메타데이터 사냥(replication-metadata hunt)도 여부와 관계없이 이를 포착합니다. (또한 control-access right에 대한 SACL 감사는 Get-Changes 4662를 통해 복제 권한 DirSync/DCSync도 마찬가지로 안정적으로 잡아냅니다.)
  • OBJECT_SECURITY DirSync는 read: AD의 호스트 읽기 감사는 신뢰할 수 없습니다. 제 테스트에서는 ReadProperty 감사 ACE가 특정 일반적인 속성 읽기에도 4662를 발생시키지 않았습니다. 따라서 SACL 카나리는 이런 은밀한 읽기를 안정적으로 잡아내지 못합니다. 대신 네트워크/ETW 캡처DirSync 베이스라인이(가) 그 역할을 맡아야 합니다.

단도직입적으로 말하면: 감사 카나리는 쓰기 쪽과 복제 권한 남용을 막는 최고의 트립와이어입니다. 하지만 은밀한 읽기는 네트워크 구간을 ‘볼 수 있는’(와이어 상시 감시) 감시가 필요합니다.

도구

저는 Red Team과 Blue Team을 위해 LDAP 확장 제어(extended controls)를 탐색하고 방어하기 위한 개념 증명(proof-of-concept) 도구 2개를 만들었습니다: 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

각 도구가 하는 일

red/ldapctl (공격용)

세 가지 하위 명령으로 구성되며, 각 명령은 검증된 확장 제어(extended-control) 기법 하나씩을 실제로 수행합니다. 전체 플래그, 권한, 출력 형식은 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.

blue/AdLdapDefense (방어용)

네 가지 탐지/강화(detection/hardening) 기능을 다루는 다섯 개의 내보낸(Exported) 함수로 구성된 PowerShell 모듈입니다. 매개변수와 샘플 출력은 blue/README.md에 있습니다. PowerShell 5.1+와 RSAT (ActiveDirectory)이 필요하며, 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


참고 자료

공유하기

더 알아보기

저자 소개

Darryl baker

Darryl Baker

수석 스태프 보안 연구원

Darryl G. Baker는 Netwrix의 수석 스태프 보안 연구원이며 Identity 및 Active Directory 보안 분야에서 널리 인정받는 권위자입니다. 10년이 넘는 아이덴티티 시스템 경험을 바탕으로 그는 Active Directory, Entra ID, Azure 환경에 초점을 둔 엔터프라이즈 보안 평가, 아이덴티티 보안 교육, 위협 에뮬레이션을 이끌어 왔습니다. Darryl은 BlueTeamCon, BSidesCT, The Experts Conference, Wild Wild West Hackin’ Fest에서 높은 평가를 받은 교육과 데모를 제공해 왔습니다. 그는 현재의 레드팀 및 블루팀 도구를 활용해 공격 경로 분석부터 위협 사냥(threat hunting)까지 수비 담당자가 모든 역량을 익힐 수 있도록 돕는 수많은 핸즈온 공격 에뮬레이션 랩의 설계자입니다. 그의 세션에서는 Darryl이 깊이 있는 기술 통찰과 실제 사례 연구를 결합하여, 블루팀 전문가들이 Identity 보안 자세를 강화하고 진화하는 공격자 기법에 대비해 방어할 수 있도록 역량을 높여 줍니다.