ปกป้องทรัพยากรจากการโจมตีเว็บด้วยการดึงข้อมูลข้อมูลเมตา

ป้องกันข้อมูลรั่วไหลเกี่ยวกับ CSRF, XSSI และข้ามต้นทาง

เหตุใดคุณจึงควรสนใจการแยกทรัพยากรบนเว็บ

เว็บแอปพลิเคชันจำนวนมากเสี่ยงต่อการถูกโจมตีแบบข้ามต้นทาง เช่น การปลอมแปลงคำขอแบบข้ามเว็บไซต์ (CSRF), การรวมสคริปต์ข้ามเว็บไซต์ (XSSI), การโจมตีแบบการจับเวลา, การรั่วไหลของข้อมูลข้ามต้นทาง หรือการโจมตีแบบ Side-Channel (Spectre) ที่ดำเนินการแบบคาดเดา

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

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

ความเข้ากันได้กับเบราว์เซอร์

เครื่องมือเบราว์เซอร์รุ่นใหม่ทั้งหมดรองรับส่วนหัวของคำขอดึงข้อมูลข้อมูลเมตา

การสนับสนุนเบราว์เซอร์

  • 76
  • 79
  • 90
  • 16.4

แหล่งที่มา

ที่มา

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

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

ขอแนะนำการดึงข้อมูลข้อมูลเมตา

ส่วนหัวของคำขอการดึงข้อมูลข้อมูลเมตาเป็นฟีเจอร์ด้านความปลอดภัยใหม่ของแพลตฟอร์มเว็บที่ออกแบบมาเพื่อช่วยเซิร์ฟเวอร์ป้องกันการโจมตีแบบข้ามต้นทาง ด้วยการให้ข้อมูลเกี่ยวกับบริบทของคำขอ HTTP ในชุดส่วนหัว Sec-Fetch-* จะทำให้เซิร์ฟเวอร์ตอบกลับใช้นโยบายความปลอดภัยได้ก่อนที่จะดำเนินการตามคำขอ ซึ่งช่วยให้นักพัฒนาแอปตัดสินใจได้ว่าจะยอมรับหรือปฏิเสธคำขอตามลักษณะคำขอและบริบทที่จะนำมาใช้งาน ทำให้สามารถตอบกลับเฉพาะคำขอที่ถูกต้องซึ่งมาจากแอปพลิเคชันของตนเองเท่านั้น

ต้นทางเดียวกัน
คำขอที่มาจากเว็บไซต์ที่ให้บริการโดยเซิร์ฟเวอร์ของคุณเอง (ต้นทางเดียวกัน) จะยังคงทำงานต่อไป คำขอดึงข้อมูลจาก https://site.example สำหรับทรัพยากร https://site.example/foo.json ใน JavaScript ทำให้เบราว์เซอร์ส่งส่วนหัวของคำขอ HTTP "Sec Fetch-Site: same-origin"
ข้ามเว็บไซต์
เซิร์ฟเวอร์อาจปฏิเสธคำขอข้ามเว็บไซต์ที่เป็นอันตรายเนื่องจากบริบทเพิ่มเติมในคำขอ HTTP จากส่วนหัว Sec-Fetch-* รูปภาพใน https://evil.example ที่กำหนดแอตทริบิวต์ src ขององค์ประกอบ img เป็น "https://site.example/foo.json" ทำให้เบราว์เซอร์ส่งส่วนหัวของคำขอ HTTP เป็น "Sec-Fetch-Site: cross-site"

Sec-Fetch-Site

การสนับสนุนเบราว์เซอร์

  • 76
  • 79
  • 90
  • 16.4

แหล่งที่มา

Sec-Fetch-Site จะบอกเซิร์ฟเวอร์ว่าเว็บไซต์ใดส่งคำขอ โดยเบราว์เซอร์จะตั้งค่านี้เป็นค่าใดค่าหนึ่งต่อไปนี้

  • same-origin หากคำขอมาจากแอปพลิเคชันของคุณเอง (เช่น site.example)
  • same-site หากคำขอมาจากโดเมนย่อยของเว็บไซต์ (เช่น bar.site.example)
  • none หากคําขอเกิดขึ้นอย่างชัดเจนจากการโต้ตอบของผู้ใช้กับ User Agent (เช่น การคลิกบุ๊กมาร์ก)
  • cross-site หากคำขอส่งโดยเว็บไซต์อื่น (เช่น evil.example)

Sec-Fetch-Mode

การสนับสนุนเบราว์เซอร์

  • 76
  • 79
  • 90
  • 16.4

แหล่งที่มา

Sec-Fetch-Mode จะระบุโหมดของคำขอ ส่วนนี้จะตรงกับประเภทของคำขอ และช่วยให้คุณสามารถแยกการโหลดทรัพยากรออกจากคำขอการนำทางได้ ตัวอย่างเช่น ปลายทาง navigate แสดงถึงคำขอการนำทางระดับบนสุด ขณะที่ no-cors ระบุคำขอทรัพยากร เช่น การโหลดรูปภาพ

Sec-Fetch-Dest

การสนับสนุนเบราว์เซอร์

  • 80
  • 80
  • 90
  • 16.4

แหล่งที่มา

Sec-Fetch-Dest แสดงปลายทางของคำขอ (เช่น หากแท็ก script หรือ img ทำให้เบราว์เซอร์ขอทรัพยากร)

วิธีใช้การดึงข้อมูลข้อมูลเมตาเพื่อป้องกันการโจมตีแบบข้ามต้นทาง

ข้อมูลเพิ่มเติมที่ส่วนหัวของคำขอเหล่านี้ให้นั้นค่อนข้างง่าย แต่บริบทเพิ่มเติมจะช่วยให้คุณสามารถสร้างตรรกะการรักษาความปลอดภัยที่มีประสิทธิภาพในฝั่งเซิร์ฟเวอร์ หรือที่เรียกว่านโยบายการแยกทรัพยากร (Resource Isolation Policy) โดยใช้โค้ดเพียงไม่กี่บรรทัด

การใช้นโยบายการแยกทรัพยากร

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

ขั้นตอนที่ 1: อนุญาตคำขอจากเบราว์เซอร์ที่ไม่ได้ส่งข้อมูลเมตาดึงข้อมูล

เนื่องจากเบราว์เซอร์บางตัวไม่รองรับการดึงข้อมูลข้อมูลเมตา คุณจึงต้องอนุญาตคำขอที่ไม่ได้ตั้งส่วนหัว Sec-Fetch-* โดยตรวจสอบว่ามี sec-fetch-site

if not req['sec-fetch-site']:
  return True  # Allow this request

ขั้นตอนที่ 2: อนุญาตคำขอที่เริ่มต้นโดยใช้เว็บไซต์เดียวกันและเบราว์เซอร์

โดยจะอนุญาตคำขอทั้งหมดที่ไม่ได้มาจากบริบทแบบข้ามต้นทาง (เช่น evil.example) โดยเฉพาะอย่างยิ่ง คำขอเหล่านี้

  • มีต้นทางมาจากแอปพลิเคชันของคุณเอง (เช่น คำขอต้นทางเดียวกันซึ่ง site.example จะส่งคำขอ site.example/foo.json เสมอ)
  • มีต้นทางมาจากโดเมนย่อย
  • เกิดขึ้นอย่างชัดเจนจากการโต้ตอบของผู้ใช้กับ User Agent (เช่น การนำทางโดยตรงหรือการคลิกบุ๊กมาร์ก ฯลฯ)
if req['sec-fetch-site'] in ('same-origin', 'same-site', 'none'):
  return True  # Allow this request

ขั้นตอนที่ 3: อนุญาตให้ใช้การนำทางระดับบนสุดและ iframe

คุณต้องอนุญาตการนำทางระดับบนสุด (HTTP GET) แบบง่ายๆ เพื่อให้เว็บไซต์ของคุณยังคงลิงก์จากเว็บไซต์อื่นได้

if req['sec-fetch-mode'] == 'navigate' and req.method == 'GET'
  # <object> and <embed> send navigation requests, which we disallow.
  and req['sec-fetch-dest'] not in ('object', 'embed'):
    return True  # Allow this request

ขั้นตอนที่ 4: เลือกไม่ใช้ปลายทางสำหรับการแสดงการเข้าชมข้ามเว็บไซต์ (ไม่บังคับ)

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

  • ปลายทางที่ต้องการให้เข้าถึงแบบข้ามต้นทาง: หากแอปพลิเคชันของคุณแสดงปลายทางที่เปิดใช้ CORS คุณต้องเลือกไม่ใช้การแยกทรัพยากรอย่างชัดเจนเพื่อให้คำขอแบบข้ามเว็บไซต์ไปยังปลายทางเหล่านี้ยังคงเป็นไปได้
  • แหล่งข้อมูลสาธารณะ (เช่น รูปภาพ รูปแบบ ฯลฯ) ทรัพยากรสาธารณะหรือทรัพยากรที่ไม่ได้ตรวจสอบสิทธิ์ซึ่งควรโหลดแบบข้ามต้นทางได้จากเว็บไซต์อื่นๆ จะได้รับการยกเว้นได้เช่นกัน
if req.path in ('/my_CORS_endpoint', '/favicon.png'):
  return True

ขั้นตอนที่ 5: ปฏิเสธคำขออื่นๆ ทั้งหมดแบบข้ามเว็บไซต์และที่ไม่ใช่การนำทาง

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

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

# Reject cross-origin requests to protect from CSRF, XSSI, and other bugs
def allow_request(req):
  # Allow requests from browsers which don't send Fetch Metadata
  if not req['sec-fetch-site']:
    return True

  # Allow same-site and browser-initiated requests
  if req['sec-fetch-site'] in ('same-origin', 'same-site', 'none'):
    return True

  # Allow simple top-level navigations except <object> and <embed>
  if req['sec-fetch-mode'] == 'navigate' and req.method == 'GET'
    and req['sec-fetch-dest'] not in ('object', 'embed'):
      return True

  # [OPTIONAL] Exempt paths/endpoints meant to be served cross-origin.
  if req.path in ('/my_CORS_endpoint', '/favicon.png'):
    return True

  # Reject all other requests that are cross-site and not navigational
  return False

การทำให้นโยบายการแยกทรัพยากรใช้งานได้

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

การระบุและการแก้ไขการละเมิดนโยบาย

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

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

การบังคับใช้นโยบายการแยกทรัพยากร

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

อ่านเพิ่มเติม