Subdomain Takeover คืออะไร? ทำไมความปลอดภัยของโดเมนถึงสำคัญกว่าที่คิด

7 นาที 13 views บันทึกเป็น PDF
Subdomain Takeover คืออะไร? ทำไมความปลอดภัยของโดเมนถึงสำคัญกว่าที่คิด

เรียนรู้เรื่อง Subdomain Takeover ช่องโหว่ที่เกิดจากการลืมลบค่า CNAME พร้อมวิธีป้องกันระบบของคุณจากการถูกยึดและการขโมยข้อมูลผู้ใช้ฉบับเข้าใจง่าย

Subdomain Takeover คืออะไร ทำไมมันถึงอันตราย

เวลาเราสร้างเว็บไซต์ เรามักจะใช้ชื่อย่อยหรือ Subdomain (ชื่อที่อยู่หน้าชื่อหลัก เช่น blog.example.com) เพื่อแยกบริการต่างๆ ออกจากกัน บางครั้งเราอาจจะไปเช่าบริการจากเจ้าอื่นมาช่วยจัดการ เช่น ใช้ CloudFront (บริการฝากไฟล์ให้โหลดเร็วขึ้นทั่วโลก) แล้วเราก็ตั้งค่าให้ชื่อนั้นชี้ไปที่เซิร์ฟเวอร์ของเขา

ปัญหาจะเกิดขึ้นเมื่อเราเลิกใช้บริการนั้น แต่เราลืมเข้าไปลบค่าที่ชี้ไปหาเขาออก ค่านี้เรียกว่า CNAME (การตั้งค่าที่บอกว่าชื่อนี้คือชื่อเดียวกับอีกที่หนึ่ง) เมื่อค่านี้ยังค้างอยู่ มันเปรียบเหมือนป้ายบอกทางที่ชี้ไปในที่ว่างเปล่า ถ้ามีคนหัวใสไปจดทะเบียนใช้บริการนั้นต่อจากเรา เขาก็จะกลายเป็นเจ้าของชื่อนั้นทันที

นี่คือสิ่งที่เรียกว่า Subdomain Takeover (การยึดชื่อย่อยไปเป็นของตัวเอง) ฟังดูเหมือนเป็นแค่การเปลี่ยนป้ายชื่อ แต่มันอันตรายกว่านั้นมาก เพราะถ้าชื่อย่อยนั้นมีความสำคัญ ระบบต่างๆ มักจะให้ความเชื่อถือมันโดยอัตโนมัติ ซึ่งอาจนำไปสู่การขโมยข้อมูลหรือยึดบัญชีผู้ใช้ได้ทั้งระบบเลยทีเดียว

ความรุนแรงของช่องโหว่ไม่ได้อยู่ที่วิธีทำ แต่อยู่ที่ความสำคัญของชื่อ

หลายคนมักเข้าใจผิดว่าถ้าเจอช่องโหว่แบบเดียวกัน ความรุนแรงต้องเท่ากัน แต่ในโลกความปลอดภัย Context (บริบทหรือความสำคัญของส่วนนั้น) คือตัวกำหนดว่าเรื่องนี้จะกลายเป็นเรื่องใหญ่แค่ไหน การยึดชื่อย่อยที่เอาไว้แค่แปะรูปภาพ กับการยึดชื่อย่อยที่เอาไว้ล็อกอิน ผลลัพธ์มันต่างกันมหาศาล

ลองนึกภาพว่าถ้าคุณทำกุญแจบ้านหาย ถ้าเป็นกุญแจห้องเก็บของหลังบ้าน คุณก็แค่เปลี่ยนล็อก แต่ถ้าเป็นกุญแจประตูหลักที่เปิดเข้าได้ทุกห้องในบ้าน นั่นคือหายนะ การยึดชื่อย่อยก็เหมือนกันครับ ถ้าชื่อนั้นถูกระบบหลักเชื่อใจ ข้อมูลสำคัญก็อาจจะหลุดออกไปได้ง่ายๆ โดยที่ตัววิธีการยึดอาจจะใช้วิธีเดิมเป๊ะๆ

ดังนั้นเวลาเราตรวจหาช่องโหว่ อย่ามองแค่ว่ามันยึดได้ไหม แต่ต้องมองว่าถ้ามีคนยึดไปแล้ว เขาจะทำอะไรกับระบบหลักของเราได้บ้าง นี่คือเหตุผลที่ทีมรักษาความปลอดภัยต้องประเมินความเสี่ยงตามความสำคัญของข้อมูล ไม่ใช่ประเมินตามเทคนิคที่ใช้ยึดเพียงอย่างเดียว

อันตรายจากการเก็บข้อมูลผู้ใช้ไว้ใน Cookie

Cookie (ไฟล์ข้อมูลเล็กๆ ที่เว็บเก็บไว้ในเครื่องเรา) เป็นตัวสำคัญที่ทำให้เราไม่ต้องล็อกอินซ้ำบ่อยๆ แต่ถ้าเราตั้งค่าขอบเขตของมันกว้างเกินไป เช่น ตั้งให้ใช้ได้กับทุกชื่อย่อยในโดเมนหลัก มันจะกลายเป็นช่องโหว่ร้ายแรงทันที เพราะถ้าชื่อย่อยไหนโดนยึดไป เขาก็จะอ่านค่านี้ได้

ลองดูตัวอย่างการตั้งค่าที่ผิดพลาดนี้ครับ

// โค้ดนี้สมมติว่าเราเก็บข้อมูลผู้ใช้ไว้ใน LocalStorage
// ถ้าตั้งค่าขอบเขตคุกกี้ไว้ที่ *.example.com จะอันตรายมาก
if (localStorage.getItem('session_id')) {
    console.log("เข้าถึงข้อมูลผู้ใช้ได้แล้ว");
}

ส่วนที่บรรทัด 3 ทำคือการดึงค่า session_id (รหัสประจำตัวการใช้งาน) ออกมา ถ้าชื่อย่อยที่โดนยึดไปมีสิทธิ์เข้าถึงคุกกี้ของโดเมนหลัก คนที่ยึดไปจะเห็นรหัสนี้ทันที ผลลัพธ์ที่ได้คือเขาสามารถปลอมตัวเป็นคุณเพื่อเข้าไปใช้งานระบบหลักได้โดยไม่ต้องรู้รหัสผ่านเลย

วิธีป้องกันที่ดีที่สุดคือการกำหนดขอบเขตให้แคบที่สุด หรือใช้สิ่งที่เรียกว่า __Host- prefix (การใส่ชื่อนำหน้าคุกกี้เพื่อล็อกให้ใช้ได้แค่ชื่อย่อยนั้นๆ) เพื่อป้องกันไม่ให้ข้อมูลหลุดไปยังชื่อย่อยอื่นๆ แม้ว่าชื่อย่อยนั้นจะถูกยึดไปแล้วก็ตาม

การเข้าใจผิดเรื่อง SameSite=Lax

หลายคนคิดว่าการตั้งค่า SameSite=Lax (การตั้งค่าไม่ให้ส่งคุกกี้ข้ามเว็บไซต์) จะช่วยป้องกันเรื่องนี้ได้ แต่ความจริงมันไม่ได้ป้องกันคนในบ้านเดียวกันครับ ถ้าผู้โจมตียึดชื่อย่อยได้ เขาจะถือว่าเป็นส่วนหนึ่งของเว็บไซต์คุณทันทีในสายตาของเบราว์เซอร์

ในมุมมองของความปลอดภัย Same-site (การที่เว็บสองเว็บอยู่ในโดเมนหลักเดียวกัน) คือการมองที่โดเมนหลัก เช่น blog.example.com กับ api.example.com ถือว่าเป็นพวกเดียวกัน ดังนั้นถ้าคุณยึดชื่อย่อยหนึ่งได้ คุณก็สามารถส่งคำสั่งไปหาอีกชื่อย่อยหนึ่งได้โดยไม่โดนเบราว์เซอร์บล็อก

นี่คือจุดที่มือใหม่พลาดบ่อยที่สุด เพราะคิดว่าการตั้งค่านี้ครอบคลุมทุกอย่างแล้ว แต่จริงๆ แล้วมันช่วยแค่ป้องกันจากเว็บภายนอกเท่านั้น ถ้าผู้โจมตีเข้ามาอยู่ในชื่อย่อยของคุณได้แล้ว การตั้งค่านี้ก็แทบจะไร้ผลทันทีครับ

เมื่อการยึดชื่อย่อยกลายเป็นช่องทางขโมยสิทธิ์ OAuth

OAuth (ระบบที่ให้เราล็อกอินผ่าน Google หรือ Facebook) เป็นอีกจุดที่เปราะบางมาก ถ้าเว็บไซต์ของคุณตั้งค่า redirect_uri (ที่อยู่ที่เว็บจะส่งผู้ใช้กลับไปหลังจากล็อกอินสำเร็จ) เป็นแบบกว้างๆ เช่น *.example.com คุณกำลังเปิดประตูให้ผู้โจมตีขโมยสิทธิ์ล็อกอินไปได้

ขั้นตอนการโจมตีมักเป็นแบบนี้ครับ:

  1. ผู้โจมตียึดชื่อย่อยที่อยู่ในเงื่อนไข redirect_uri ของคุณ
  2. เขาหลอกให้เหยื่อกดลิงก์ล็อกอินที่ส่งไปยังชื่อย่อยนั้น
  3. ระบบล็อกอินส่งรหัสผ่านชั่วคราวไปให้ผู้โจมตีแทนที่จะเป็นเว็บหลัก

ผลลัพธ์คือผู้โจมตีจะได้รหัสผ่านชั่วคราวไปครอบครองโดยที่เหยื่อไม่รู้ตัวเลย วิธีแก้เรื่องนี้ง่ายมากคือต้องตั้งค่า redirect_uri ให้เป็นค่าที่แน่นอน (Exact-match) เท่านั้น ห้ามใช้เครื่องหมายดอกจันหรือรูปแบบกว้างๆ เด็ดขาด เพราะมันคือความเสี่ยงที่เลี่ยงได้

สรุปแนวทางการป้องกันและนำไปใช้จริง

การป้องกัน Subdomain Takeover ไม่ใช่เรื่องของการเปลี่ยนโค้ดให้ซับซ้อน แต่เป็นการจัดการ Configuration (การตั้งค่าระบบ) ให้รัดกุม สิ่งที่ต้องทำทันทีคือการไล่ตรวจสอบค่า CNAME ทั้งหมดที่ชี้ไปยังบริการภายนอกว่ายังใช้งานอยู่จริงหรือไม่

ถ้าคุณเป็นโปรแกรมเมอร์มือใหม่ นี่คือเช็คลิสต์ที่คุณควรทำทุกครั้งที่ดูแลระบบ:

  • ตรวจสอบ CNAME ที่ไม่ได้ใช้งานแล้วลบออกทันที
  • กำหนดขอบเขตคุกกี้ให้แคบที่สุดเท่าที่เป็นไปได้
  • ตั้งค่า OAuth ให้ระบุที่อยู่ปลายทางแบบเจาะจงเสมอ
  • หมั่นตรวจสอบการตั้งค่าความปลอดภัยของโดเมนหลักและโดเมนย่อยอยู่เสมอ

จำไว้ว่าความปลอดภัยไม่ได้มาจากการแก้บั๊กเพียงอย่างเดียว แต่มาจากการเข้าใจว่าแต่ละส่วนในระบบเชื่อมโยงกันอย่างไร ความรอบคอบในการตั้งค่าคือด่านแรกที่สำคัญที่สุด ของการเป็นโปรแกรมเมอร์มืออาชีพครับ


ที่มา: Subdomain Takeover Severity Comes From Security Context, Not the Exploit Mechanism — DEV Community

แชร์บทความ

Facebook X LINE

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

จัดการเซิร์ฟเวอร์ผ่าน VS Code ให้ง่ายขึ้นด้วย Easy SSH พร้อมฟีเจอร์โหลดไฟล์ผ่านคลิกเดียว

จัดการเซิร์ฟเวอร์ผ่าน VS Code ให้ง่ายขึ้นด้วย Easy SSH พร้อมฟีเจอร์โหลดไฟล์ผ่านคลิกเดียว

เบื่อไหมที่ต้องสลับหน้าจอไปมาเพื่อจัดการเซิร์ฟเวอร์? มาลองใช้ Easy SSH ปลั๊กอิน VS Code ที่ช่วยให้คุณรีโมทผ่าน Terminal ได้สะดวก แถมโหลดไฟล์ได้ง่ายแค่กด Ctrl+click

ที่มา: DEV Community

6 hours ago 11 นาที
3 views
วิธีดึงข้อมูลราคาจาก Google Hotels ด้วย API สำหรับนักพัฒนา

วิธีดึงข้อมูลราคาจาก Google Hotels ด้วย API สำหรับนักพัฒนา

อยากทำแอปท่องเที่ยวแต่ดึงข้อมูลราคาจาก Google Hotels ไม่ได้? มาดูวิธีใช้ Apify Actor ช่วยดึงข้อมูลแบบอัตโนมัติด้วย Python ง่ายๆ ไม่ต้องกลัวเว็บพัง

ที่มา: DEV Community

10 hours ago 8 นาที
5 views
วิธีเช็กความพร้อมโปรเจกต์ก่อนปล่อยงานจริงด้วย ReleaseReady

วิธีเช็กความพร้อมโปรเจกต์ก่อนปล่อยงานจริงด้วย ReleaseReady

เคยไหม? โค้ดรันได้ในเครื่องแต่พอปล่อยจริงกลับพัง! มาดูวิธีตรวจสอบความพร้อมของโปรเจกต์ก่อนอัปขึ้น GitHub ด้วยเครื่องมือ ReleaseReady กัน

ที่มา: DEV Community

14 hours ago 9 นาที
6 views