ดูเหตุผลที่ต้องใช้การแยกแบบข้ามต้นทางเพื่อใช้ฟีเจอร์ที่มีประสิทธิภาพ เช่น SharedArrayBuffer
, performance.measureUserAgentSpecificMemory()
และตัวจับเวลาความละเอียดสูงที่มีความแม่นยำมากขึ้น
บทนำ
ในการทำให้เว็บไซต์ "แยกแบบข้ามต้นทาง" โดยใช้ COOP และ COEP เราได้อธิบายวิธีปรับใช้สถานะ "แยกแบบข้ามต้นทาง" โดยใช้ COOP และ COEP บทความนี้เป็นบทความประกอบที่อธิบาย เหตุผลที่ต้องใช้การแยกแบบข้ามต้นทางเพื่อเปิดใช้ฟีเจอร์ที่มีประสิทธิภาพในเบราว์เซอร์
ฉากหลัง
เว็บสร้างขึ้นจากนโยบายต้นทางเดียวกัน ซึ่งเป็นฟีเจอร์ความปลอดภัยที่จำกัดวิธีที่เอกสารและสคริปต์โต้ตอบกับทรัพยากรจากต้นทางอื่น หลักการนี้
จำกัดวิธีที่เว็บไซต์เข้าถึงทรัพยากรข้ามต้นทางได้ เช่น ระบบจะป้องกันไม่ให้เอกสารจาก https://a.example
เข้าถึงข้อมูล
ที่โฮสต์ใน https://b.example
อย่างไรก็ตาม นโยบายต้นทางเดียวกันมีข้อยกเว้นในอดีตบางประการ เว็บไซต์ใดก็ได้ทำสิ่งต่อไปนี้
- ฝัง iframe แบบข้ามต้นทาง
- รวมทรัพยากรข้ามต้นทาง เช่น รูปภาพหรือสคริปต์
- เปิดหน้าต่างป๊อปอัปข้ามต้นทางด้วยการอ้างอิง DOM
หากออกแบบเว็บใหม่ตั้งแต่ต้น ก็จะไม่มีข้อยกเว้นเหล่านี้ น่าเสียดายที่เมื่อชุมชนเว็บตระหนักถึงประโยชน์หลักของ นโยบายต้นทางเดียวกันอย่างเข้มงวด เว็บก็พึ่งพาข้อยกเว้นเหล่านี้อยู่แล้ว
เราได้แก้ไขผลข้างเคียงด้านความปลอดภัยของนโยบายต้นทางเดียวกันที่หละหลวมดังกล่าวใน 2
วิธี วิธีหนึ่งคือการเปิดตัวโปรโตคอลใหม่ที่เรียกว่าการแชร์ทรัพยากรข้ามโดเมน (CORS)
ซึ่งมีจุดประสงค์เพื่อให้มั่นใจว่าเซิร์ฟเวอร์อนุญาตให้แชร์ทรัพยากรกับต้นทางที่กำหนด อีกวิธีหนึ่งคือการนำสิทธิ์เข้าถึงสคริปต์โดยตรงไปยังทรัพยากรข้ามต้นทางออกโดยนัยในขณะที่ยังคงรักษาความเข้ากันได้แบบย้อนหลัง เราเรียกทรัพยากรข้ามต้นทางดังกล่าวว่าทรัพยากร "ทึบแสง" เช่น นี่คือเหตุผลที่การ
จัดการพิกเซลของรูปภาพแบบข้ามโดเมนผ่าน CanvasRenderingContext2D
จะล้มเหลว เว้นแต่จะใช้ CORS กับรูปภาพ
การตัดสินใจเกี่ยวกับนโยบายทั้งหมดนี้เกิดขึ้นภายในกลุ่มบริบทการเรียกดู
เป็นเวลานานแล้วที่การผสมผสานระหว่าง CORS และทรัพยากรที่ทึบแสงก็เพียงพอที่จะทำให้เบราว์เซอร์ปลอดภัย บางครั้งก็พบเคสข้อยกเว้น (เช่น ช่องโหว่ของ JSON) และจำเป็นต้องแก้ไข แต่โดยรวมแล้วหลักการที่ไม่อนุญาตให้มีสิทธิ์การอ่านโดยตรงไปยังไบต์ดิบของทรัพยากรข้ามต้นทางก็ประสบความสำเร็จ
แต่ทุกอย่างเปลี่ยนไปเมื่อมี Spectre ซึ่ง
ทำให้ข้อมูลใดก็ตามที่โหลดไปยังกลุ่มบริบทการท่องเว็บเดียวกันกับโค้ดของคุณ
อาจอ่านได้ การวัดเวลาที่การดำเนินการบางอย่างใช้จะช่วยให้ผู้โจมตี
คาดเดาเนื้อหาของแคช CPU และเนื้อหาของหน่วยความจำ
ของกระบวนการได้ การโจมตีตามเวลาดังกล่าวสามารถทำได้ด้วยตัวจับเวลาที่มีความละเอียดต่ำ
ซึ่งมีอยู่ในแพลตฟอร์ม แต่สามารถเร่งให้เร็วขึ้นได้ด้วยตัวจับเวลาที่มีความละเอียดสูง
ทั้งแบบชัดแจ้ง (เช่น performance.now()
) และแบบโดยนัย (เช่น
SharedArrayBuffer
s) หาก evil.com
ฝังรูปภาพข้ามต้นทาง ผู้โจมตีจะใช้การโจมตี Spectre เพื่ออ่านข้อมูลพิกเซลของรูปภาพได้ ซึ่งจะทำให้การป้องกันที่อาศัย "ความทึบ" ไม่ได้ผล
ในอุดมคติแล้ว คำขอข้ามโดเมนทั้งหมดควรได้รับการตรวจสอบอย่างชัดเจนโดยเซิร์ฟเวอร์ ที่เป็นเจ้าของทรัพยากร หากเซิร์ฟเวอร์ที่เป็นเจ้าของทรัพยากรไม่ได้ให้การตรวจสอบ ข้อมูลจะไม่เข้าสู่กลุ่มบริบทการท่องเว็บของผู้ไม่ประสงค์ดี และจะอยู่นอกเหนือการเข้าถึงของการโจมตี Spectre ที่หน้าเว็บอาจดำเนินการได้ เราเรียกสถานะนี้ว่าสถานะแยกแบบข้ามต้นทาง ซึ่งเป็นสิ่งที่ COOP+COEP ทำ
ในสถานะที่แยกต้นทางแบบข้ามต้นทาง ระบบจะถือว่าเว็บไซต์ที่ขอมีความอันตรายน้อยกว่า
และจะปลดล็อกฟีเจอร์ที่มีประสิทธิภาพ เช่น SharedArrayBuffer
,
performance.measureUserAgentSpecificMemory()
และตัวจับเวลาความละเอียดสูงที่มีความแม่นยำมากขึ้น ซึ่งอาจ
ใช้ในการโจมตีที่คล้ายกับ Spectre ได้ และยังป้องกันไม่ให้มีการแก้ไข
document.domain
ด้วย
นโยบายเครื่องมือฝังแบบข้ามต้นทาง
นโยบายเครื่องมือฝังแบบข้ามต้นทาง (COEP) ป้องกันไม่ให้เอกสารโหลดทรัพยากรข้ามต้นทางใดๆ ที่ไม่ได้ให้สิทธิ์แก่เอกสารอย่างชัดเจน (โดยใช้ CORP หรือ CORS) ฟีเจอร์นี้ช่วยให้คุณประกาศได้ว่าเอกสารโหลดทรัพยากรดังกล่าวไม่ได้
หากต้องการเปิดใช้งานนโยบายนี้ ให้ต่อท้ายส่วนหัว HTTP ต่อไปนี้ในเอกสาร
Cross-Origin-Embedder-Policy: require-corp
COEP ใช้ค่าเดียวคือ require-corp
ซึ่งบังคับใช้นโยบายที่ว่าเอกสารจะโหลดได้เฉพาะทรัพยากรจากต้นทางเดียวกัน หรือทรัพยากรที่ทำเครื่องหมายอย่างชัดเจนว่าโหลดได้จากต้นทางอื่น
หากต้องการโหลดทรัพยากรจากต้นทางอื่น ทรัพยากรนั้นต้องรองรับ กลไกการแชร์ทรัพยากรข้ามโดเมน (CORS) หรือนโยบายทรัพยากรแบบข้ามต้นทาง (CORP)
กลไกการแชร์ทรัพยากรข้ามโดเมน
หากทรัพยากรข้ามโดเมนรองรับกลไกการแชร์ทรัพยากรข้ามโดเมน
(CORS) คุณอาจใช้แอตทริบิวต์
crossorigin
เพื่อโหลดไปยังหน้าเว็บโดยไม่ถูก COEP บล็อก
<img src="https://third-party.example.com/image.jpg" crossorigin>
ตัวอย่างเช่น หากแสดงทรัพยากรรูปภาพนี้ด้วยส่วนหัว CORS ให้ใช้แอตทริบิวต์
crossorigin
เพื่อให้คำขอเรียกข้อมูลทรัพยากรใช้โหมด CORS ซึ่งยัง
ป้องกันไม่ให้โหลดรูปภาพ เว้นแต่จะตั้งค่าส่วนหัว CORS
ในทำนองเดียวกัน คุณอาจดึงข้อมูลข้ามต้นทางผ่านเมธอด fetch()
ซึ่งไม่จำเป็นต้องมีการจัดการพิเศษตราบใดที่เซิร์ฟเวอร์ตอบกลับด้วยส่วนหัว HTTP ที่ถูกต้อง
นโยบายทรัพยากรข้ามต้นทาง
นโยบายทรัพยากรข้ามต้นทาง (CORP) เดิมทีเปิดตัวเป็นตัวเลือกเพื่อปกป้องทรัพยากรของคุณจากการโหลดโดยต้นทางอื่น ในบริบทของ COEP นั้น CORP สามารถระบุนโยบายของเจ้าของทรัพยากรสำหรับผู้ที่โหลดทรัพยากรได้
ส่วนหัว Cross-Origin-Resource-Policy
มีค่าที่เป็นไปได้ 3 ค่า ดังนี้
Cross-Origin-Resource-Policy: same-site
โหลดทรัพยากรที่ทำเครื่องหมาย same-site
ได้จากเว็บไซต์เดียวกันเท่านั้น
Cross-Origin-Resource-Policy: same-origin
โหลดทรัพยากรที่ทำเครื่องหมาย same-origin
ได้จากแหล่งที่มาเดียวกันเท่านั้น
Cross-Origin-Resource-Policy: cross-origin
เว็บไซต์ใดก็ได้สามารถโหลดทรัพยากรที่ทำเครื่องหมาย cross-origin
(ค่านี้ได้รับการเพิ่มลงใน
ข้อกำหนด CORP พร้อมกับ COEP)
นโยบายเครื่องมือเปิดแบบข้ามต้นทาง
นโยบายการเปิดข้ามต้นทาง
(COOP) ช่วยให้คุณมั่นใจได้ว่า
หน้าต่างระดับบนสุดจะแยกออกจากเอกสารอื่นๆ โดยการวางเอกสารเหล่านั้นไว้ใน
กลุ่มบริบทการท่องเว็บที่แตกต่างกัน เพื่อให้เอกสารเหล่านั้นโต้ตอบกับ
หน้าต่างระดับบนสุดโดยตรงไม่ได้ ตัวอย่างเช่น หากเอกสารที่มี COOP เปิดป๊อปอัป พร็อพเพอร์ตี้ window.opener
จะเป็น null
นอกจากนี้ พร็อพเพอร์ตี้ .closed
ของการอ้างอิงของหน้าต่างที่เปิดไปยังหน้าต่างนี้จะแสดงผล true
ส่วนหัว Cross-Origin-Opener-Policy
มีค่าที่เป็นไปได้ 3 ค่า ดังนี้
Cross-Origin-Opener-Policy: same-origin
เอกสารที่ทำเครื่องหมาย same-origin
จะแชร์กลุ่มบริบทการท่องเว็บเดียวกันกับเอกสารที่มาจากต้นทางเดียวกันซึ่งทำเครื่องหมาย same-origin
อย่างชัดเจนได้
Cross-Origin-Opener-Policy: same-origin-allow-popups
เอกสารระดับบนสุดที่มี same-origin-allow-popups
จะเก็บการอ้างอิงถึงป๊อปอัปใดๆ
ซึ่งไม่ได้ตั้งค่า COOP หรือเลือกไม่ใช้การแยกโดย
ตั้งค่า COOP เป็น unsafe-none
Cross-Origin-Opener-Policy: unsafe-none
unsafe-none
เป็นค่าเริ่มต้นและอนุญาตให้เพิ่มเอกสารลงในกลุ่มบริบทการเรียกดูของหน้าต่างที่เปิดเอกสาร เว้นแต่หน้าต่างที่เปิดเอกสารจะมี COOP เป็น same-origin
สรุป
หากต้องการรับประกันการเข้าถึงฟีเจอร์ที่มีประสิทธิภาพ เช่น SharedArrayBuffer
,
performance.measureUserAgentSpecificMemory()
หรือตัวจับเวลาความละเอียดสูงที่มีความแม่นยำมากขึ้น โปรดทราบว่า
เอกสารของคุณต้องใช้ทั้ง COEP ที่มีค่าเป็น require-corp
และ
COOP ที่มีค่าเป็น same-origin
หากไม่มีทั้ง 2 อย่าง เบราว์เซอร์จะ
ไม่รับประกันการแยกที่เพียงพอเพื่อเปิดใช้ฟีเจอร์ที่มีประสิทธิภาพเหล่านั้นอย่างปลอดภัย คุณ
สามารถพิจารณาสถานการณ์ของหน้าเว็บได้โดยตรวจสอบว่า
self.crossOriginIsolated
แสดงผลเป็น true
หรือไม่
ดูขั้นตอนการติดตั้งใช้งานได้ที่การทำให้เว็บไซต์เป็น "แบบข้ามต้นทาง ที่แยกกัน" โดยใช้ COOP และ COEP