เจาะลึกช่องโหว่ที่เกี่ยวข้องกับ Kerberos Authentication

27 กรกฎาคม 2020

พิชญะ โมริโมโต
พิชญะ โมริโมโตหัวหน้าทีมทดสอบเจาะแฮกระบบ (lead penetration tester) ของบริษัท สยามถนัดแฮก, เป็นที่ปรึกษาด้านความปลอดภัยให้หน่วยงานเอกชน, เป็นที่รู้จักกันในฐานะ หนึ่งในแอดมินกลุ่ม 2600 Thailand และเป็นหนึ่งในคนเขียนบทความลงเพจ สอนแฮกเว็บแบบแมว ๆ

วันนี้เราจะมาพูดถึงการจำลองการเจาะระบบธนาคารกัน โดยธนาคารเราจะตั้งชื่อให้ว่า “ธนาคารสยามโดนแฮก” ซึ่งเป็นธนาคารจำลองไม่มีอยู่จริง โดยจะใช้เทคนิคเกี่ยวกับ Kerberos Authentication ซึ่งโดยทั่วไประบบไอทีภายในองค์กรขนาดใหญ่ ที่เป็น Windows Domain ก็จะมีให้ใช้กัน

สำหรับคนไม่รู้จัก Windows Domain เล่าง่าย ๆ คือปกติเรามีคอมฯ ส่วนตัวซื้อมาลง Windows ไว้ใช้คนเดียว ก็ใช้ได้แหละ แต่ถ้าในบริษัทที่จะต้องมีคอมฯ 100 เครื่อง มีเซิร์ฟเวอร์ 500 เครื่อง ถ้าให้คนไอทีไปบริหารจัดการทีละเครื่อง ก็คงน่าปวดหัวน่าดู Microsoft เลยมีแนวคิดว่า เราสามารถนำเครื่องคอมฯ ต่าง ๆ มาเชื่อมต่อกันทำให้คนไอทีสามารถบริหารจัดการควบคุมจากจุดศูนย์กลางได้ ซึ่งปกติแล้วจุดที่ว่านั้นจะเป็น Windows Server ที่ตั้งมาทำหน้าที่เป็น Active Directory Domain Services (AD DS)

ที่คนไอทีเรียกกันย่อ ๆ ว่าเครื่อง AD หรือเครื่อง Domain Controller นั้นเอง (ต่อไปจะขอเรียกว่าเครื่อง DC) โดยเครื่องคอมฯ ที่มาต่อกันให้ควบคุมผ่าน DC ได้จะเรียกว่า domain-joined computer (หรือ user computer หรือ server) หรือภาษาไอทีแบบบ้าน ๆ เราเรียกกันว่า “เครื่องที่ join AD แล้ว” เราก็จะมีชื่อเรียกที่ตั้งมาเรียกวงระบบคอมฯ ที่มาต่อ ๆ กันนี้เป็นชื่อ Windows Domain นั้น ๆ (เพราะจริง ๆ มีมากกว่า 1 ได้ แต่ไม่ขอพูดถึงนะ) โดยในบทความนี้ ธนาคารสยามโดนแฮก จะใช้ชื่อว่า sdh.sth.local (ต่อไปจะขอเรียกแทนว่า domain แต่ อย่าสับสนกับ domain name ที่เป็นชื่อเว็บล่ะ คนละอย่างกัน)

ตัวอย่างหน้าจอเครื่อง DC ที่ว่า

แต่เดิมตอนเรามีคอมฯ ที่เป็น Windows อยู่เครื่องเดียว พวก username / password ที่เราเอาไว้ใช้ล็อกอินเข้าคอมฯ เราก็จะเก็บในคอมฯ ของเราอย่างเดียว ซึ่งจะเก็บอยู่ในไฟล์ C:\windows\system32\config\SAM เราจะเรียก user account พวกนี้ว่า local user account (ตามหลักความปลอดภัยแล้ว ถ้าเลือกได้ ในองค์กรไม่ควรให้พนักงานใช้ local user โดยตรง)

แต่พอองค์กรเปลี่ยนมาใช้เป็น DC พวก username / password ของพนักงานในองค์กร ก็จะไม่ได้เก็บในคอมฯ ของพนักงานแต่ละคนแล้ว แต่จะเก็บรวม ๆ กันไว้ใน DC แทน (ปกติแล้วจะเก็บอยู่ในไฟล์ C:\Windows\NTDS\ntds.dit) เพื่อให้พนักงานไอทีที่ดูแล DC สามารถบริหารจัดการ user account ต่าง ๆ ได้ ซึ่งเราจะเรียก user account พวกนี้ว่าเป็น domain user

เพิ่มเติมคือ ในบริบทของ Windows Domain ข้อมูลที่เก็บอยู่ในศูนย์กลางตรงนี้จะเรียกว่า object เช่น user account ต่าง ๆ ก็ด้วย แล้วก็สิ่งที่เป็นคุณสมบัติของ object ก็จะเรียกว่า attribute (เบื้องหลังคือเก็บเป็น directory service และเรียกดูหรือแก้ไขได้ผ่าน LDAP) ตัวอย่างเช่น user account ก็จะมี attribute ว่าอยู่ในกลุ่ม (domain user group) อะไร หรือบอกว่ามีการตั้งค่าอะไรไว้บ้างเช่น ยอมให้รหัสผ่านไม่มีวันหมดอายุ พวกการตั้งค่านี้ก็จะเก็บเป็น attribute ต่าง ๆ

ถัดมาเวลา คอมฯ เครื่องหนึ่งใน domain จะต่อไปหาคอมฯ อีกเครื่อง ไม่ว่าจะผ่าน Remote Desktop Protocol (RDP) หรือผ่าน network service ใด ๆ อย่าง Microsoft Exchange, SharePoint, MS SQL ต่าง ๆ นา ๆ ก็จะต้องมี Network Authentication Protocol เข้ามาจัดการว่า เอ๊ะ! เวลามีคอมฯ ใน computer network จะล็อกอินข้ามกัน ทำยังไงดีนะถึงจะปลอดภัย โดยใน domain จะมีการทำ Network Authentication หลัก ๆ แล้ว 2 วิธีด้วยกันคือ

1. NTLM (ที่เป็น Challenge-Response Protocol นะอย่าสับสนกับ NTLMv1 / NTLMv2 ที่เป็น hash function คนละอันกัน ชื่อมันคล้าย ๆ กัน อาจจะเรียกว่า Net-NTLM ก็ได้)

2. Kerberos หลายคนอาจจะงงว่า เฮ้ย! เราแค่จะล็อกอินเข้าระบบ ทำไมมันต้องทำให้มันยุ่งยากขนาดนี้เนี่ย ทำไมเราไม่ทำแบบเว็บ แค่เราพิมพ์ username / password แล้ว web browser ส่งไปถาม server ผ่าน HTTP Protocol ก็จบแล้วป่ะ?

คำตอบก็คือ ความยุ่งยากของ NTLM กับ Kerberos ออกแบบมาให้ปลอดภัยกว่านิดหน่อย ในแง่มุมว่า

  • ถ้าเกิดมีผู้ไม่ประสงค์ดี เข้ามาดักข้อมูล (Man-in-the-Middle) ภายในองค์กรได้ ต่อให้ดักได้ ก็จะไม่ได้รหัสผ่านไปตรง ๆ เพราะรหัสผ่านจะไม่ได้มีการส่งกันตรง ๆ เหมือนเว็บ (เดี๋ยวเรามาดูกันว่าแล้วมันทำยังไง)
  • รองรับการทำ Single Sign-On (SSO) ด้วยข้อมูลพนักงานที่มีอยู่แล้วใน DC คือในองค์กร อาจจะมีระบบ 100 ระบบ เราอาจจะไม่ควรมีฐานข้อมูลแยกสำหรับเก็บ username / password สำหรับพนักงานทุกคนในทุก ๆ 100 ระบบนั้น ถ้าเราเก็บ username / password ของพนักงานไว้ใน DC จากนั้น ถ้าใครจะล็อกอินเข้าระบบอะไรก็ให้มาถามที่ DC แทนจะดีกว่า ชีวิตการบริหารระบบไอทีในองค์กรจะสบายขึ้นเยอะ
  • อีกอย่างคือ มันจะมีเรื่องของ credential delegation ด้วย เช่น มันจะมีกรณีที่ user A มาล็อกอินที่เครื่อง B จากนั้น ณ เครื่อง B จะต้องใช้ user A ล็อกอินต่อไปเครื่อง C ต่อ จะทำยังไงถึงจะปลอดภัย? (ถ้าส่งรหัสผ่านของ user A ไปเก็บไว้ในเครื่อง B ตรง ๆ ก็ไม่ปลอดภัยดิ)

ในบทความ “มาลองแฮก Windows ด้วยเทคนิค LLMNR/NBNS Poisoning” ก่อนหน้านี้ ผู้เขียนเคยเล่าเรื่องการทำงานและช่องโหว่ที่เกี่ยวข้องกับ NTLM ไปแล้ว ในครั้งนี้เป็นมหากาพย์ภาคต่อ ว่าเราจะมาดูฝั่ง Kerberos กันบ้างว่า มีอะไรน่าสนใจ ในมุมของทางด้านความมั่นคงปลอดภัยระบบสารสนเทศ

Kerberos คืออะไร?

Kerberos เป็นหมาสามหัว! ฮ่ง ๆ!

ที่มารูป: https://www.youtube.com/watch?v=uUCKpo5VpDk

ตึ่งโป๊ะ.. Kerberos เป็นมาตรฐานสำหรับการยืนยันตัวตนผ่านระบบเครือข่าย (Network Authentication Protocol) ตัวหนึ่ง ที่ระบุว่าถ้าผู้ใช้งานบนคอมฯ ใด ๆ เวลาจะทำการยืนยันตัวตน (ล็อกอิน) ไปใช้งานระบบใด ๆ ในระบบเครือข่าย จะต้องทำยังไง โดยหลักการในภาพรวมคือผู้ใช้งานจะไปขอตั๋ว (Kerberos ticket) มาจากเซิร์ฟเวอร์ที่ทำหน้าที่เป็น Kerberos Distribution Center (KDC) จากนั้นเอาตั๋วนั้นไปโชว์ให้เครื่องปลายทางที่เราจะล็อกอิน เพื่อการเข้าไปใช้

ทำงานอย่างไร

Kerberos จะต้องมีส่วนเซิร์ฟเวอร์เอาไว้ยืนยันตัวตนชื่อว่า Key Distribution Center (KDC) ซึ่งประกอบไปด้วยอีก 2 ส่วนย่อยคือ Authentication Server (AS) กับ Ticket Granting Server (TGS)

เวอร์ชันเต็ม ๆ จะซับซ้อนหน่อย แต่จะเล่าแบบเข้าใจง่าย ๆ ก่อนละกันคือจะมี 6 ขั้นตอนดังรูป คือสมมุติ Client Computer ต้องการจะเข้าไปใช้ MS SQL Server

1. ขั้นตอน AS-REQ

Client Computer จะส่งชื่อ Username ที่จะล็อกอินไปหา KDC (AS) เพื่อขอตั๋ว ตัวอย่างนี้คือของ longcat

2. ขั้นตอน AS-REP

KDC (AS) จะตอบกลับมา 2 อย่างคือ

1. ตั๋วเอาไว้ยืนยันคนที่ขอล็อกอินเรียกว่า Ticket Granting Ticket (TGT) ซึ่งตั๋วนี้จะถูกเข้ารหัสไว้โดยที่คนขอจะถอดรหัสไม่ได้ (และไม่จำเป็นจะต้องถอดรหัส TGT) แต่เอาไปใช้ต่อที่ TGS ได้ ถ้ามี session key
2. ข้อมูลเพิ่มเติมอีกส่วน ที่ถูกเข้ารหัสด้วยรหัสผ่านของ domain user account ที่ขอไป (longcat) ซึ่งจะมีค่ากุญแจชั่วคราว (session key) และอื่น ๆ

จากนั้นคนขอถ้าเป็นตัวจริงก็จะสามารถถอดรหัสข้อมูลเพิ่มเติม (ส่วนที่ 2) และเอา session key ออกมาได้ ด้วยการใช้รหัสผ่านของตัวเอง (ในตัวอย่างนี้คือ รหัสผ่านของ longcat)

3. ขั้นตอน TGS-REQ

Client Computer พอได้ตั๋ว TGT พร้อมกับ session key ก็จะเอาไปคุยกับ KDC อีกรอบแต่คราวนี้จะคุยกับส่วน TGS เพื่อขออีกตั๋ว เรียกว่า service ticket เพื่อเข้าไปใช้งานระบบอื่นเช่น MS SQL Server

4. ขั้นตอน TGS-REP

ซึ่ง TGS ก็จะตอบกลับเพื่อให้ service ticket ใครก็ตามที่เอา TGT กับ session key มาขอเสมอ (แต่จะเอา service ticket ไปแล้วใช้ได้หรือเปล่าอีกเรื่อง) โดยใน service ticket ก็จะมีระบุว่าคนที่ขอไป เป็นใครขอเมื่อไร

5. ขั้นตอน AP-REQ

ต่อมา Client Computer ก็จะส่ง service ticket ไปยัง MS SQL Server ที่ตัวเองต้องการจะเชื่อมต่อ เพื่อขอเข้าไปใช้งานระบบ โดยลืมบอกไปว่า service ticket จะโดนเข้ารหัสอยู่ซึ่งจะมี service account (คือ domain user ที่สร้างมาไว้สำหรับเข้าไปใช้งาน service เท่านั้น) ของ MS SQL Server คนเดียว ที่จะถอดรหัสได้ พอ MS SQL Server ได้รับ service ticket ก็จะตรวจสอบดูข้างในว่า Client Computer เป็นใคร ควรเข้าระบบตัวเองได้หรือเปล่า

6. ขั้นตอน AP-REP

MS SQL Server หลังตรวจสอบว่าคนขอเป็นใคร มีสิทธิ์เข้าระบบหรือเปล่า ก็จะตอบกลับไปว่ายอมให้ Client Computer เข้าระบบไหม หรือเริ่มการเชื่อมต่อหลังเข้าสู่ระบบได้ทันทีเลย

หมายเหตุ: ของจริงจะซับซ้อนกว่านี้ผู้เขียนเว้นรายละเอียดหลายอย่างให้เข้าใจง่ายขึ้น

ถ้าสำหรับคนไอทีทั่วไป ต้องการจะเข้าใจเบื้องต้นว่า Kerberos คืออะไรเฉย ๆ รู้แค่ 1-6 ขั้นตอนด้านบนก็เพียงพอแล้ว *กดปิด* แต่ถ้าเราอยากจะเข้าใจถึงขั้นว่า Kerberos อาจมีช่องโหว่ หรือข้อสังเกตที่ทำให้โดนแฮกได้ยังไง ก็จะต้องเข้าใจลึกเข้าไปอีก ในแต่ละขั้นตอน ถ้าลองคิด ด้วยวิชาแฮกเกอร์ หรือความคิดโจร ๆ หน่อยจะพบว่า กระบวนการที่ว่ามามันมี จุดน่าสนใจหลายอย่างเช่น…

AS-REP Roasting

ถ้าเป็นจริงตามที่เล่ามา จากขั้นตอนที่ 1 (AS-REQ) กับ 2 (AS-REP) แฮกเกอร์ซึ่งจะเป็นใครก็ได้ (ที่ไม่ใช่ longcat จริง ๆ) ก็อาจจะสามารถส่งชื่อ Username ของเหยื่อ (longcat) ไปถาม KDC (AS) ว่าอยากจะล็อกอินเป็น longcat จากนั้นพอ AS-REP ตอบ TGT กับ ค่ากุญแจชั่วคราว (session key) ที่โดนเข้ารหัสอยู่ ด้วยกุญแจที่เป็น รหัสผ่านของ longcat กลับมา แฮกเกอร์แม้ถอดรหัสโดยตรงไม่ได้ก็ยังสามารถ นำข้อมูลเข้ารหัสนั้นไปทำ การแคร็ก (offline password cracking) หรือลองเดารหัสผ่านไปเรื่อย ๆ ได้ ! การโจมตีนี้ มีชื่อเรียกว่า AS-REP Roasting

ข้อมูลเข้ารหัส ใน AS-REP = encrypt( secret key = NT Hash(รหัสผ่านของ longcat ซึ่งแฮกเกอร์ไม่รู้แต่ลองเดาได้), data = [ session key, timestamp, IP คนขอ, … ] )

พอลองเดาไปเรื่อย ๆ จนถอดรหัสข้อมูลนั้นได้ ก็จะทำให้แฮกเกอร์รู้รหัสผ่านของ longcat

ดังนั้น Kerberos เลย พยายามจะป้องกัน AS-REP Roasting โดยการทำสิ่งที่เรียกว่า Kerberos Pre-Authentication โดยวิธีการคือ ในขั้นตอนที่ 1 (AS-REQ) นอกจากจะส่งแค่ชื่อ Username (longcat) ไปขอกับ KDC (AS) แล้ว จะต้อง เอารหัสผ่านของตัวเอง (ค่า NT hash ของ longcat) ไปเข้ารหัส timestamp (เวลาปัจจุบัน) ส่งไปพร้อมกันด้วย เมื่อ AS รับค่ามาก็จะลองเอา รหัสผ่านของ longcat (ค่า NT hash) ที่ตัวเองมีเก็บไว้ (เพราะ KDC คือ dc) มาลองแกะดูว่าได้ timestamp (เวลา) ใกล้เคียงเวลาปัจจุบัน จริง ๆ ไหม ถ้าได้จริง แสดงว่าคนที่ขอมาในขั้นตอน AS-REQ เป็น longcat จริง ๆ โดย

AS-REQ ที่ทำ Kerberos Pre-Authentication ของ longcat จะต้องส่งค่า…
= encrypt( secret key = NT Hash(รหัสผ่านของ longcat), data = [ timestamp] )
แนบไปด้วยตอนขอ

เอาละ เรามาดูการใช้ต่อ Kerberos จริง ๆ จากค่าใน network packet กันดีกว่า

ในวงสีแดงด้านขวาบนจะเห็นว่า AS-REQ มีส่งไป 2 ครั้ง โดยครั้งแรกจะลองขอธรรมดาก่อน ปรากฏว่า KDC (AS) ตอบกลับมาว่า ต้องทำ Kerberos Pre-Authentication ก่อน (KRB5DC_ERR_PREAUTH_REQUIRED) ดังนั้น Client Computer จึงต้องส่ง AS-REQ ไปใหม่อีกครั้งคราวนี้นอกจากชื่อ Username (longcat) แล้ว ยังต้องเข้ารหัสเวลาปัจจุบันไปด้วยดังในวงสีแดงซ้ายล่างของรูป ก็จะทำให้แฮกเกอร์ไม่สามารถ กดขอ AS-REP ของคนอื่นเอามาลองแคร็กได้ เพราะเมื่อ KDC (AS) แกะค่านี้ไม่ออก หรือไม่เจอ timestamp ในระยะเวลา +- ไม่กี่นาทีตามที่กำหนด ก็จะไม่ยอมส่ง AS-REP กลับไปนั้นเอง

โดยปกติแล้ว Kerberos Pre-Authentication จะเปิดไว้เป็นค่าเริ่มต้น แต่ก็เคยเจอว่ามีคนเผลอไปกดปิดมันเพื่อเชื่อมต่อ domain user account นั้นกับระบบอะไรบางอย่างแบบเก่า (หรืออยากให้ Kerberos เร็วขึ้น?) ทำให้เกิดช่องโหว่ที่โดนโจมตีด้วยเทคนิค AS-REP Roasting ได้นั้นเอง

ดังตัวอย่างการตั้งค่า Domain User ในรูปต่อไปนี้

 

วิธีโจมตีด้วย AS-REP Roasting

การโจมตีภายใต้เงื่อนไข ผู้โจมตี รู้ชื่อ domain user account เหยื่อที่ปิด Kerberos Pre-Authentication

ใช้โปรแกรม GetNPUsers.py ของ Impacket (https://github.com/SecureAuthCorp/impacket/blob/master/examples/GetNPUsers.py) ทำการขอ AS-REP ของ domain user account เหยื่อ จาก KDC (AS) ในตัวอย่างนี้คือเครื่อง 10.100.1.4 และเหยื่อคือ sth-victim3

$ GetNPUsers.py sth/sth-victim3 -request -no-pass -dc-ip 10.100.1.4

 

จากนั้นทำการแคร็กค่า ข้อมูลเข้ารหัส ใน AS-REP ที่ได้มา ด้วยเทคนิค AS-REP Roasting ด้วยโปรแกรม hashcat เราจะได้ รหัสผ่านของเหยื่อ (sth-victim3)

พบว่าได้รหัสผ่าน (sth-victim3) คือ P@ssw0rd123

วิธีป้องกัน / แก้ไขปัญหา AS-REP Roasting

จะต้องทำการตรวจสอบว่า ใน dc (Active Directory) ไม่มี domain user account ที่ปิด Kerberos Pre-Authentication อยู่ โดยสามารถทำได้โดยการรัน query ใส่ LDAP ของ dc โดยใช้ attribute ที่เก็บสถานะของ Kerberos Pre-Authentication ไว้เป็นเงื่อนไข

(&(objectclass=user)(objectcategory=user)(useraccountcontrol:1.2.840.113556.1.4.803:=4194304))

ถ้าเจอก็ให้ไปติ๊ก “Do not require Kerberos preauthentication” ใน Property ของ domain user นั้นออก!

หมายเหตุ: ที่ Active Directory Users and Computers > Users > คลิกขวาไปที่ User ที่ต้องการแก้ไข > Properties > Account เลื่อน Account options ลงมาและทำการยกเลิก “Do not require Kerberos preauthentication”

AS-REQ Pre-Authentication Roasting

ย้อนกลับไปอ่านขั้นตอน 1-6 ของ Kerberos อีกรอบ แล้วถ้าเรายังใช้จินตนาการ เพิ่มเข้าไปอีกนิดหน่อย จะพบว่าในขั้นตอนการทำ Kerberos Pre-Authentication ที่ว่ามา ก็ยังมีจุดสังเกตว่า ถ้าแฮกเกอร์สามารถ ดัก network packet จังหวะที่เหยื่อ (longcat) กำลังทำขั้นตอนที่ 1 (AS-REQ) ซึ่งจะมีการส่ง ข้อมูลเข้ารหัส โครงสร้างหน้าตาประมาณ… (แบบย่อๆ)

ข้อมูลเข้ารหัสใน AS-REQ ที่เปิดการทำ Kerberos Pre-Authentication = encrypt( secret key = NT Hash(รหัสผ่านของ longcat), data = [ timestamp] )

จะพบว่า จริง ๆ แล้วถ้าเราดัก AS-REQ อันนี้จาก longcat ตัวจริงได้ แฮกเกอร์จะสามารถ ลองแกะค่าข้อความเข้ารหัสนี้ เป็นการแคร็ก เพื่อหารหัสผ่านของ longcat ได้อยู่ดี!! แต่ AS-REQ Pre-Authentication Roasting จะโดนเอาไปแคร็กยากกว่า AS-REP Roasting พอสมควร เพราะว่าแฮกเกอร์จะต้องดักข้อมูล ณ จุดที่เหยื่อ (longcat) กดล็อกอินโดยใช้ Kerberos ในขณะที่ AS-REP Roasting (ไม่ได้เปิด Kerberos Pre-Authentication) แฮกเกอร์จะส่ง AS-REQ ไปขอ ค่าที่เอามาแคร็กเพื่อหารหัสผ่านของเหยื่อเมื่อไรก็ได้

โดยการแคร็กที่เราพูดถึงใน AS-REP Roasting กับ AS-REQ Pre-Authentication Roasting จะเป็นการแคร็ก ที่แตกต่างจากการเดาสุ่มรหัสใส่ KDC (AS) โดยตรง เพราะว่าเป็นการแคร็กแบบ offline บนเครื่องของแฮกเกอร์เอง โดยไม่ต้องส่งรหัสผ่านที่จะเดาผ่าน network packet (ไม่มีปัญหาเรื่อง network latency) และไม่เกิด log บนเครื่อง DC หลบการตรวจจับการเดารหัสผ่านเกือบทุกชนิดได้ แถมยังไม่ทำให้ user account เหยื่อที่เราจะเดารหัสผ่านโดนล็อคจากการเดาผิดหลายครั้งด้วยนาจา

วิธีการโจมตี AS-REQ Pre-Authentication Roasting

กรณีที่เปิด AS-REQ Pre-Authentication แล้วแต่โดนดักค่า AS-REQ

แฮกเกอร์จะต้องทำการดักข้อมูลเหยื่อด้วยการทำ ARP Spoofing วงแลนหรือโจมตีช่องโหว่แฮกเข้าไปใน Router ขององค์กรได้ก่อน ในตัวอย่างนี้ จะเป็นการ ดักข้อมูล ไว้แล้วเก็บเป็นไฟล์ pcap แล้วเอาไปเปิดในโปรแกรม NetworkMiner (https://www.netresec.com/?page=NetworkMiner) เพื่อแกะค่าใน format ที่เอาไปใส่ในโปรแกรมเพื่อแคร็กได้ออกมา

แฮกเกอร์สามารถนำค่าที่ดักได้ในจังหวะ AS-REQ Pre-Authentication นี้ไปทำการลองแคร็กด้วยโปรแกรม JohnTheRipper (https://github.com/magnumripper/JohnTheRipper)

# https://github.com/magnumripper/JohnTheRipper
$ cat hash.txt
$krb5pa$18$adminuser2$SDH.STH.LOCAL$SDH.STH.LOCALadminuser2$29bc93628bcb9e31a564df0e2bacc563e35dfc15e962a6439fd89da1d3af0f5559e7627fc084229197d78831da8d4e859e3e58f0a0c4ab18
$ john --format=krb5pa-sha1-opencl --wordlist=wordlist.txt hash.txt
[...]
P@ssw0rd1234     (?)
1g 0:00:00:05 DONE (2020-07-16 14:15) 0.1834g/s 183.8p/s 183.8c/s 183.8C/s 123456..P@ssw0rd1234
Use the "--show" option to display all of the cracked passwords reliably
Session completed.

จะพบว่ารหัสผ่านของเหยื่อคือ P@ssw0rd1234

วิธีป้องกัน / แก้ไขปัญหา AS-REQ Pre-Authentication Roasting

ไม่มีวิธีแก้ไขโดยตรง แต่สามารถลดความเสี่ยงได้ด้วยการ ป้องกันไม่ให้แฮกเกอร์มาดักข้อมูลใน computer network ขององค์กรได้ตั้งแต่แรก รวมถึงการกำหนด นโยบายการตั้งรหัสผ่าน (password policy) ของ domain user account ให้แข็งแรง ก็จะทำให้ต่อให้แฮกเกอร์ดักเอา AS-REQ ไปได้ ก็ไม่สามารถแคร็กออกได้โดยง่าย

Kerberoasting และ Silver Ticket

ข้อสังเกตอีกอย่างคือ AS-REP Roasting กับ AS-REQ Pre-Authentication Roasting เนี่ย คนไม่ค่อยรู้จักแล้วก็ไม่ค่อยมีใครทำกัน เพราะมันทำได้ค่อนข้างยาก (อันนึงไม่ใช่ค่าเริ่มต้น ส่วนอีกอันต้องดักข้อมูลตอนเหยื่อกดล็อกอินได้) สิ่งที่แฮกเกอร์ (หรือนักทดสอบเจาะระบบอย่าง penetration tester) มักจะทำกันจะเป็นเทคนิคถัดไปที่จะเล่ามากกว่า เรียกว่า Kerberoasting (มาจากคำว่า Kerberos + Roasting) โดยหลักการ เราจะต้องย้อนกลับไปดูขั้นตอน 1-6 ของ Kerberos ใหม่อีกรอบ ในขั้นตอนที่ 4 (TGS-REP) จังหวะที่ KDC (TGS) ตอบ service ticket กลับมา จริง ๆ ค่า service ticket ที่ตอบกลับมานี้จะโดนเข้ารหัสอยู่ด้วยรหัสผ่านของ service account (NT hash ของ domain user account ที่ผูกกับ service นั้น ๆ)

service ticket = encrypt( secret key = NT Hash(รหัสผ่านของ service account), data = [ ชื่อ username ที่เข้ามาขอ, วันหมดอายุ, timestamp, IP คนขอ และอื่น ๆ … ] )

ผนวกรวมกับข้อเท็จจริงของ Kerberos ในขั้นตอนที่ 3 (AS-REQ) ที่ว่า ใครก็ได้ สามารถไปขอ service ticket ของ service ใด ๆ กับ KDC (TGS) ได้ ทำให้ แฮกเกอร์ (ที่มี domain user สักคนในระบบ) สามารถแกล้งไปขอ service ticket มาจากนั้น เอามาลองแคร็กหา “รหัสผ่านของ service account” (ในสมการด้านบน) ซึ่งโดยปกติแล้ว มักจะถูกกำหนดเป็นรหัสผ่านที่ไม่มีวันหมดอายุซะด้วย

โดยถ้าตั้งรหัสผ่านไว้ไม่ปลอดภัย แฮกเกอร์ก็อาจจะแคร็กรหัสผ่านของ service account ออก แล้วสามารถนำรหัสผ่านที่ได้นั้นไป..

  • ใช้ซ้ำกับระบบต่าง ๆ หรือล็อกอินเข้าไปเป็น service account หากได้สิทธิ์สูง อยู่ในกลุ่ม domain user group เทพ ๆ ก็อาจจะถึงขั้นเจาะเข้า dc ไปยึดบัญชีและเซิร์ฟเวอร์เกือบทุกเครื่องในระบบองค์กร เลยก็เป็นได้ (ซึ่งก็พบได้บ่อย ๆ ว่าเกิดกรณีแบบนี้ขึ้น)
  • นำไปแก้ไขค่า service ticket ให้แฮกเกอร์สามารถปลอมตัวเป็นคนอื่นใน service นั้น ๆ ได้ หรือสร้าง service ticket ที่ไม่มีวันหมดอายุ (แก้ไขวันหมดอายุ) จริง ๆ คือแก้ได้ทุกอย่างตามที่เก็บอยู่ใน service ticket นั้นเอง และ service ticket ที่ถูกแก้ไขนี้จะถูกเรียกว่า “silver ticket”

วิธีการโจมตี Kerberoasting

กรณีดังต่อไปนี้สามารถโดนโจมตีด้วยเทคนิค Kerberoasting ได้

ในวง domain ในองค์กรปกติ ก็อาจจะมี network service ต่าง ๆ เช่น MS SQL, SharePoint, Exchange ตัว network service เหล่านี้ก็จะต้องมี domain user account เข้ามาใช้โดยจะเรียกว่า service account ซึ่งจะมีการตั้งชื่อเรียกว่า Service Principal Name (SPN) แล้วนำ domain user account ไปผูกกับชื่อ SPN

ฟีเจอร์อย่างหนึ่งที่ Windows Domain ยอมให้เกิดขึ้นคือ ถ้าเรามี domain user account ใด ๆ ในวง domain เดียวกัน เราจะเรียกดูได้ว่ามีชื่อ SPN อะไรลงทะเบียนไว้แล้วบ้าง นอกจากนั้นเรายังขอ TGT (จาก AS-REP ในขั้นตอนที่ 2 ของกระบวนการ Kerberos) แล้วเอา TGT ไปขอ service ticket จาก TGS (TGS-REP ในขั้นตอนที่ 4 ของกระบวนการ Kerberos) โดยสามารถใช้โปรแกรม GetUserSPNs.py จากชุดโปรแกรม Impacket มาดึง service ticket เก็บไว้ในไฟล์ (tgshash.txt) ได้ด้วย ดังนี้

# https://github.com/SecureAuthCorp/impacket/blob/master/examples/GetUserSPNs.py
$ GetUserSPNs.py -request sdh.sth.local/sth-victim2:P@ssw0rd123 -dc-ip 10.100.1.4 -outputfile tgshash.txt
Impacket v0.9.21 - Copyright 2020 SecureAuth Corporation
ServicePrincipalName                      Name           MemberOf  PasswordLastSet             LastLogon                   Delegation
----------------------------------------  -------------  --------  --------------------------  --------------------------  ----------
HTTP/lab1-iisftpvm.sth.local              iis_service              2020-07-14 12:40:41.350479  2020-07-14 13:07:41.244334
MSSQLSvc/lab1-mssqlvm.sdh.sth.local:1433  mssql_service            2020-07-16 00:18:10.727225  2020-07-15 16:39:22.791548
HTTP2/sdh.sth.local                       iis_svc                  2020-07-15 23:23:16.989089  <never>

ซึ่งอย่างที่อธิบายไปก่อนหน้าว่าในขั้นตอนที่ 4 (TGS-REP) ของกระบวนการทำ Kerberos ค่า service ticket นี้ถูกเข้ารหัสมาด้วยรหัสผ่านของ service account (จริง ๆ คือ NT hash) ดังนั้นค่าที่ได้มา เราก็สามารถลองเอาไปใช้โปรแกรม JohnTheRipper ทำการลองแคร็ก service ticket ได้ดังนี้

(ในตัวอย่างนี้คือเราเก็บค่า NT hash ของ service account ชื่อ SPN ว่า MSSQLSvc/lab1-mssqlvm.sdh.sth.local:1433 ไว้ในไฟล์ชื่อ tgshash.txt)

$ john --format=krb5tgs --wordlist=rockyou.txt tgshash.txt
Using default input encoding: UTF-8
Loaded 3 password hashes with 3 different salts (krb5tgs, Kerberos 5 TGS etype 23 [MD4 HMAC-MD5 RC4])
Press ‘q’ or Ctrl-C to abort, almost any other key for status
Passw0rd         (?)
Passw0rd         (?)
IL0vey0u         (?)
3g 0:00:00:19 DONE (2020-07-16 00:31) 0.1550g/s 573234p/s 574081c/s 574081C/s ILA2003..IL0VELENA
Use the “--show” option to display all of the cracked passwords reliably
Session completed.

จะพบว่าแฮกเกอร์สามารถแคร็กรหัสผ่านของ service account ต่าง ๆ ที่ตั้งมาอย่างไม่ปลอดภัยออกมาได้ จากนั้นสามารถนำมาสร้าง silver ticket ต่อได้ (คือเอามาถอดรหัส service ticket เดิม แก้ไข แล้วเข้ารหัสกลับไปใหม่) ดังนี้

  • ขั้นแรกต้องดูค่า SID เลขของตัวเอง
  • แล้วก็สร้างค่า NT hash จากรหัสผ่านของ service account ที่เราได้มา เพราะต้องเอาไปเข้ารหัส service ticket ด้วย NT hash ของรหัสผ่านของ service account ผู้เขียนใช้ภาษา Python เขียนเองเพื่อทำ hash function แบบ MD4 ซึ่งก็คือ NT hash นั้นแหละ
C:\Users\sth-victim2>whoami /user

USER INFORMATION
----------------
User Name       SID
=============== ===========================================
sth\sth-victim2 S-1-5-21-422520243-1488181621-61289240-1110
$ cat ntlm_hash.py
import hashlib,binascii
import sys
h = hashlib.new('md4', sys.argv[1].encode('utf-16le')).digest()
print(binascii.hexlify(h))
$ python ntlm_hash.py "IL0vey0u"
b'f4e818b57a5ac3b4f4ea31fb14e5fdeb'

ต่อมามาสร้าง Silver Ticket กันเลยโดยใช้โปรแกรม Mimikatz (https://github.com/gentilkiwi/mimikatz)

C:\Users\sth-victim2> mimikatz.exe
[...]
mimikatz # kerberos::golden /sid:S-1-5-21-422520243-1488181621-61289240-1110 /domain:sth.local /ptt /target:lab1-mssqlvm.sdh.sth.local:1433 /service:MSSQLSvc /rc4:f4e818b57a5ac3b4f4ea31fb14e5fdeb /user:somchai /id:1110

จากนั้นจากแฮกเกอร์ที่เป็น sth-victim2 จะสามารถสร้าง silver ticket (ซึ่งก็คือ service ticket ที่แฮกเกอร์แก้ค่าข้างในเองไปแล้ว) ของ somchai ขึ้นมา แล้วใส่ไว้ใน session ปัจจุบัน (ด้วยออฟชั่น /ptt) จากนั้นลองเอาไปต่อเครื่อง MS SQL เซิร์ฟเวอร์ จะพบว่าสามารถเข้าใช้งานด้วยสิทธิ์ของ somchai ได้

ในมุมแฮกเกอร์ ในการโจมตีจริง ๆ จะขึ้นอยู่กับระบบปลายทางที่เราสามารถแก้ service ticket ได้ว่า เมื่อเราแก้ไปแล้ว สามารถทำให้ network service ปลายทางเชื่ออะไรผิด ๆ ได้บ้าง นอกเหนือจากนั้นก็จะเป็นการได้รหัสผ่าน หรือบัญชีของ service account นั้นไปใช้ ซึ่งก็จะต้องดูสิทธิ์อีกทีว่าทำอะไรได้บ้าง

วิธีป้องกัน / แก้ไขปัญหา Kerberoasting

ไม่มีวิธีการแก้ไขโดยตรงแต่ลดความเสี่ยงได้โดยการ…

  1. ควรใช้แนวทางการออกแบบระบบอย่างปลอดภัยแบบ Principle of least privilege (POLP) โดยการกำหนดสิทธิ์ที่ทำได้ของ service account แต่ละอันให้ต่ำที่สุด ให้แค่เท่าที่จำเป็นต้องใช้ โดยเฉพาะอย่างยิ่ง ห้ามไม่อยู่ในกลุ่ม domain group ที่เกี่ยวกับ admin ต่าง ๆ
  2. ควรไปตั้งค่า service account ให้เป็น “Account is sensitive and cannot be delegated” ถ้าหาก service account นั้นไม่จำเป็นต้องนำรหัสผ่านของตัวเองไปใช้ต่อกับ service อื่น
  3. 3. สุ่มรหัสผ่านมาตั้งให้ปลอดภัยเดาไม่ได้ หรือดีสุด ๆ คือ กำหนดให้ service account นั้นอยู่ในกลุ่ม Managed Service Account (MSA) หรือ Group Managed Service Account (gMSA) ซึ่งจะบังคับสุ่มตั้งรหัสผ่านยาว 120 ตัว เปลี่ยนเองทุก 30 วัน

หมายเหตุ: เหตุผลที่รหัสผ่านเราไม่จำเป็นต้องตั้งง่าย ๆ และให้มันสุ่มเปลี่ยนบ่อย ๆ ได้ เพราะเวลามีคนเข้ามาเรียกใช้ service โดยการยืนยันตัวตนผ่าน Kerberos มันจะเรียกผ่านชื่อ SPN ไม่จำเป็นต้องรู้รหัสผ่านของ service account นั้น ๆ ก็ได้ แต่เรื่องของ SPN อยู่นอกเหนือขอบเขตของบทความนี้ใครสนใจไปหาอ่านต่อกันเองนะจ๊ะ

Golden Ticket

หลังจากที่เราเห็นการ Roasting มาตั้งแต่ AS-REP Roasting, AS-REQ Pre-Authentication Roasting, Kerberoasting (จริง ๆ มันก็คือ TGS-REP Roasting อ่านะ) ต่อมา เราจะมาดูเทคนิค สุดเทพที่ส่วนตัวผู้เขียนเรียกเทคนิคนี้ว่าเป็น god mode นั้นก็คือ Golden Ticket .. บัตรทอง 30 บาท แฮกได้ทุกเครื่อง

โดยการจะเข้าใจ Golden Ticket ผู้อ่านจะต้องกลับไปรีวิวขั้นตอน 1-6 ของ Kerberos ใหม่อีกรอบ จะพบว่าในขั้นตอนที่ 2 (AS-REP) ค่าที่ KDC (AS) ตอบกลับมาจะมีตั๋วของคนที่มาขอ (กรณีนี้คือ longcat) ที่เรียกว่า TGT ซึ่งค่า TGT ที่ว่าเนี่ย มันเป็นสิ่งใช้ยืนยันตัวตนประกอบกับ session key ว่าคนที่จะขอต่อเข้า service (กับ TGS) เป็นใคร ทีนี้เนี่ยเจ้า TGT นี้จริง ๆ มันก็เป็นแค่ ก้อนค่าเข้ารหัสอีกเช่นกัน โครงสร้างหน้าตาโดยย่อ ๆ ประมาณ…

TGT = encrypt ( secret key = NT Hash(รหัสผ่านของ krbtgt), data = [ ชื่อ user ที่มาล็อกอิน, session key ของ user ที่มาล็อกอิน, วันหมดอายุ และอื่น ๆ ] )

ซึ่งก็หมายความได้ว่า ทุก ๆ ค่า TGT ของ domain user account ใครก็ตามที่ไปขอมาจาก KDC (AS) มันจะเป็นค่าที่ถูกเข้ารหัสโดยรหัสผ่านของ domain user account ของ Kerberos เองชื่อว่า krbtgt (ย่อมาจาก Key Distribution Center Service Account หรือมันคือ service account ของ Kerberos service นั้นเอง ตัว KDC ใน Kerberos มันก็เป็น Windows service อันนึง) ซึ่งรหัสผ่านของ krbtgt นี้จะถูกสุ่มมาเป็นค่ายาว ๆ ตอนติดตั้ง dc และไม่ควรมีใครรู้

จะเกิดอะไรขึ้นถ้าแฮกเกอร์ไปรู้ค่า รหัสผ่านของ krbtgt (จริง ๆ คือเป็นค่า NT Hash ของรหัสผ่านอีกทีก็พอ) ที่เอาไว้สร้าง TGT ได้? สิ่งที่จะเกิดขึ้นก็คือแฮกเกอร์จะสร้าง TGT ปลอม โดยใส่ชื่อ user ที่มาล็อกอินเป็นใครก็ได้ แก้วันหมดอายุเป็นเมื่อไรก็ได้ จากนั้นเอา TGT นี้ไป ขอ service ticket เข้าไป ทะลวงเซิร์ฟเวอร์ต่าง ๆ ในองค์กรรัว ๆ โดยตั๋ว TGT ที่แฮกเกอร์สร้างมาใหม่เองในกรณีนี้จะเรียกว่า Golden Ticket

คำถามที่น่าสนใจก็คือ แล้วแฮกเกอร์จะไปรู้รหัสผ่านของ krbtgt ได้ยังไง? คำตอบมีเพียง แฮกเกอร์ ต้องแฮกเข้าไปในเครื่อง Domain Controller (dc) ให้ได้ก่อน !!!?? จากนั้นจึงแฮกเข้าไปเอารหัสผ่านของ krbtgt

ดังนั้น Golden Ticket จริง ๆ แล้วจึงไม่ใช่ท่าแฮก แต่เป็นท่าที่เอาไว้ ทำให้แฮกเกอร์ที่แฮกเข้าไปเรียบร้อยแล้ว สามารถแฝงตัวอยู่ในระบบได้อย่างแนบเนียน และนานที่สุดเท่าที่จะเป็นไปได้

ทางที่จะหยุด ตั๋วทอง 30 บาท แฮกทุกโรคได้ คือต้องเปลี่ยนรหัสผ่านของ krbgtg ซึ่งปกติแล้วรหัสผ่านของ krbtgt จะไม่มีใครอยู่ดี ๆ ตั้งใจไปเปลี่ยนมัน และไม่ค่อยมีคนไอทีกล้าไปเปลี่ยน เพราะถ้าทำอะไรพลาดมาละก็.. เสียหายหลายบาทแน่นอน เพราะ dc เก็บข้อมูลคอมฯ และ Kerberos มีผู้ใช้ทั้งระบบองค์กร!

โดยตัวอย่างเทคนิคที่จะได้รหัสผ่านของ krbtgt หลังจากแฮก dc ได้แล้วมีหลายท่ามากเช่น

1. DCSync

วิธีนี้จะต้องเป็น domain user ที่มีสิทธิ์ในกลุ่ม domain group ที่ยอมให้ทำ domain replication ตัวอย่างเช่น กลุ่ม domain admin ก็จะสามารถใช้ฟีเจอร์ของ Active Directory ชื่อว่า DCSync ที่จริง ๆ เอาไว้ใช้ backup หรือ sync ข้อมูลของ user object ข้าม dc แต่ แฮกเกอร์ (ที่ยึด dc ได้แล้ว) เอาฟีเจอร์นี้มาใช้อ่านรหัสผ่านของ domain user ชื่อ krbtgt แทน โหดร้ายมาก

วิธีการทำ DCSync ด้วยโปรแกรม Mimikatz บนเครื่อง dc ด้วยสิทธิ์ domain admin ทำได้ดังในรูปนี้

จะเจอว่าได้ค่า NT hash ของ krbtgt คือ 26efa3472d1c325ca1e8446b5635dab3

2. ntds.dit

จากที่ผู้เขียนเกริ่นไปตอนต้นว่า domain user จะเก็บในไฟล์ชื่อว่า ntds.dit บนเครื่อง dc ดังนั้นถ้าแฮกเกอร์สามารถแฮก dc เข้าไปได้ก็อาจจะขโมยไฟล์ ntds.dit ที่ว่านี้ไปแกะเอารหัสผ่านของ krbtgt ออกมาได้

ข่าวร้ายสำหรับแฮกเกอร์คือ ปกติแล้ว Windows จะไม่ยอมให้เปิดอ่านหรือก๊อปไฟล์ ntds.dit ออกมา T_T

ส่วนข่าวดี ก็คือ ต่อให้เราก๊อปไฟล์ขโมยออกมาตรง ๆ ไม่ได้ เราสามารถใช้ลูกเล่นได้อะ แฮกเกอร์ ต้องไม่ทำท่าธรรมดาอยู่แล้วจริงไหม?

ลูกเล่นที่ว่าก็คือ เราก๊อปไฟล์ ntds.dit ออกมาตรง ๆ ไม่ได้ก็จริง แต่เราสามารถไปเปิดฟีเจอร์ backup ของ Windows (ชื่อว่า Shadow Copy) ให้ทำการ backup ไดรฟ์ C ซะเลย จากนั้น เราก็ไปดึงเอาไฟล์ ntds.dit ออกมาจาก backup แทน ! เวรี่อีซี่ ทำได้โดยใช้คำสั่ง vssadmin ดังในรูปด้านล่างนี้

อีกปัญหาคือไฟล์ ntds.dit นี้ต่อให้เราออกมาได้มันจะโดนเข้ารหัสไว้อยู่ดี โดยกุญแจจะถูกเก็บไว้ใน Windows Registry เราจะต้องอ่านค่ากุญแจออกมาเก็บเป็นไฟล์ก่อน (กรณีนี้คือ system.hiv) ดังในรูปนี้

จากนั้นนำไฟล์ ntds.dit และกุญแจ system.hiv ออกมาแล้วใช้โปรแกรม secretsdump.py ในชุดโปรแกรม Impacket จะสามารถอ่านรหัสผ่านของ krbtgt ได้เช่นกัน

# https://github.com/SecureAuthCorp/impacket/blob/master/examples/secretsdump.py
$ secretsdump.py -ntds ntds.dit -system system.hiv local

ผลก็จะคล้ายกับการทำ DCSync จะได้ค่า NT hash ของ krbtgt ออกมาคือ 26efa3472d1c325ca1e8446b5635dab3 (ค่าเดียวกันเลย)

สุดท้ายเมื่อได้รหัสผ่านของ krbtgt (ค่า NT hash) ด้วยวิธีใดก็ตาม แฮกเกอร์ก็สามารถใช้โปรแกรม Mimikatz มาสร้าง Golden Ticket (TGT ที่แฮกเกอร์แก้ไขเนื้อหาข้างในเองได้) ดังนี้

mimikatz # privilege::debug
mimikatz # kerberos::golden /user:sth-hackerman /domain:sdh.sth.local /sid:S-1-5-21-422520243-1488181621-61289240 /krbtgt:26efa3472d1c325ca1e8446b5635dab3 /ptt
[...]
mimikatz # misc::cmd

จากนั้นทำการ ลองเข้าไป ไปยังเครื่อง 10.100.1.15

C:\Users\adminuser\Downloads>psexec.exe \\10.100.1.15 cmd.exe

PsExec v2.2 - Execute processes remotely
Copyright (C) 2001-2016 Mark Russinovich
Sysinternals - www.sysinternals.com


Microsoft Windows [Version 10.0.14393]
(c) 2016 Microsoft Corporation. All rights reserved.

C:\windows\system32>

เมื่อไปดูใน Event Log ของ dc จะพบว่า คนที่เข้ามาด้วย session ของ Golden Ticket จะกลายเป็น sth-hackerman ได้นั้นเอง แล้วก็ TGT นี้จะหมดอายุอีกปีที 2030 คือแอบเก็บไว้ใช้เข้าสู่ระบบได้ไปอีก 10 ปี !

หลังจากผู้อ่านได้เห็นการที่ระบบใน Windows Domain ของธนาคารสยามโดนแฮก โดนระเบิดกันไปแล้ว ก็หวังว่าจะได้ความรู้กันหลายอย่าง ไม่ว่าจะเป็นเรื่องการตั้ง password policy ให้ปลอดภัย การดูแลใส่ใจในส่วนของ service account ในองค์กร และการจำกัดสิทธิ์กลุ่ม domain admin ให้น้อยที่สุดเพื่อความปลอดภัย เพราะถ้าโดนแฮกไปแล้ว ข้อมูลผู้ใช้งานและระบบอื่น ๆ ในองค์กรอาจได้รับความเสียหายร้ายแรงได้นั่นเอง

 

บทความที่เกี่ยวข้อง