ดูเหตุผลที่ต้องใช้การแยกแบบข้ามต้นทางเพื่อใช้ฟีเจอร์ที่มีประสิทธิภาพ เช่น 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
) หาก evil.com
ฝังรูปภาพข้ามแหล่งที่มา ผู้โจมตีอาจใช้การโจมตี Spectre เพื่ออ่านข้อมูลพิกเซลของรูปภาพ ซึ่งทำให้การป้องกันที่อาศัย "ความทึบแสง" ไร้ประสิทธิภาพ
โดยหลักการแล้ว เซิร์ฟเวอร์ที่เป็นเจ้าของทรัพยากรควรตรวจสอบคำขอข้ามแหล่งที่มาทั้งหมดอย่างชัดเจน หากเซิร์ฟเวอร์ที่เป็นเจ้าของทรัพยากรไม่ได้ดำเนินการตรวจสอบ ข้อมูลจะไม่เข้าสู่กลุ่มบริบทการท่องเว็บของผู้ไม่ประสงค์ดี และจะไม่อยู่ในขอบเขตการโจมตี Spectre ที่หน้าเว็บอาจดำเนินการได้ เราเรียกสถานะนี้ว่าสถานะแยกต่างหากแบบข้ามต้นทาง ซึ่งก็คือสิ่งที่ COOP+COEP มุ่งเน้น
ภายใต้สถานะแยกกันข้ามต้นทาง ระบบจะถือว่าเว็บไซต์ที่ขอมีอันตรายน้อยกว่า ซึ่งจะปลดล็อกฟีเจอร์ที่มีประสิทธิภาพ เช่น SharedArrayBuffer
,
performance.measureUserAgentSpecificMemory()
และตัวจับเวลาความละเอียดสูงที่มีความแม่นยำมากขึ้น ซึ่งอาจนำไปใช้ในการโจมตีแบบ Spectre ได้ และยังป้องกันไม่ให้แก้ไข document.domain
นโยบายเครื่องมือฝังแบบข้ามต้นทาง
นโยบายเครื่องมือฝังแบบข้ามต้นทาง (COEP) ป้องกันไม่ให้เอกสารโหลดทรัพยากรข้ามต้นทางที่ไม่ได้ให้สิทธิ์เอกสารอย่างชัดเจน (โดยใช้ CORP หรือ CORS) ฟีเจอร์นี้ช่วยให้คุณประกาศได้ ว่าเอกสารโหลดทรัพยากรดังกล่าวไม่ได้
หากต้องการเปิดใช้งานนโยบายนี้ ให้เพิ่มส่วนหัว HTTP ต่อไปนี้ต่อท้ายเอกสาร
Cross-Origin-Embedder-Policy: require-corp
คีย์เวิร์ด require-corp
เป็นค่าเดียวที่ยอมรับสำหรับ COEP ซึ่งจะบังคับใช้นโยบายว่าเอกสารจะโหลดได้เฉพาะทรัพยากรจากต้นทางเดียวกัน หรือทรัพยากรที่ทำเครื่องหมายไว้อย่างชัดเจนว่าโหลดได้จากต้นทางอื่น
ทรัพยากรต้องรองรับกลไกการแชร์ทรัพยากรข้ามโดเมน (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
ของ opener จะแสดงผลเป็น 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
หากไม่มีสิ่งใดสิ่งหนึ่ง เบราว์เซอร์จะไม่รับประกันการแยกที่เพียงพอเพื่อเปิดใช้ฟีเจอร์ที่มีประสิทธิภาพเหล่านั้นอย่างปลอดภัย คุณระบุสถานการณ์ของหน้าเว็บได้โดยดูว่า self.crossOriginIsolated
แสดงผลเป็น true
หรือไม่
ดูขั้นตอนการใช้งานได้ที่การทําให้เว็บไซต์ "แยกแหล่งที่มา" โดยใช้ COOP และ COEP