การทำให้เว็บไซต์ "แยกแบบข้ามต้นทาง" โดยใช้ COOP และ COEP

ใช้ COOP และ COEP เพื่อตั้งค่าสภาพแวดล้อมที่แยกแบบข้ามต้นทางและเปิดใช้ฟีเจอร์ประสิทธิภาพสูง เช่น SharedArrayBuffer, performance.measureUserAgentSpecificMemory() และตัวจับเวลาความละเอียดสูงที่แม่นยำยิ่งขึ้น

ข้อมูลอัปเดต

  • 21 มิถุนายน 2022: สคริปต์ของผู้ปฏิบัติงานก็ต้องได้รับการดูแลเมื่อมีการเปิดใช้การแยกแบบข้ามต้นทาง เพิ่มคำอธิบาย
  • 5 ส.ค. 2021: มีการกล่าวถึง JS Self-Profiling API ว่าเป็น API หนึ่งที่ต้องมีการแยกแบบข้ามต้นทาง แต่แสดงถึงการเปลี่ยนแปลงทิศทางล่าสุด จึงถูกนำออก
  • 6 พฤษภาคม 2021: จากความคิดเห็นและปัญหาที่รายงาน เราได้ตัดสินใจที่จะปรับไทม์ไลน์สำหรับการใช้งาน SharedArrayBuffer ในเว็บไซต์ที่ไม่มีการแยกแบบข้ามต้นทางที่จะถูกจำกัดใน Chrome M92
  • 16 เมษายน 2021: เพิ่มหมายเหตุเกี่ยวกับโหมดใหม่ของ COEP แบบไม่มีข้อมูลเข้าสู่ระบบ และ COOP ที่มาจากแหล่งเดียวกันที่อนุญาตสำหรับการแยกแบบข้ามต้นทาง
  • 5 มีนาคม 2021: ลบข้อจำกัดสำหรับ SharedArrayBuffer, performance.measureUserAgentSpecificMemory() และฟังก์ชันการแก้ไขข้อบกพร่อง ซึ่งตอนนี้เปิดใช้อย่างเต็มรูปแบบแล้วใน Chrome 89 เพิ่มความสามารถที่กำลังจะเปิดตัว performance.now() และ performance.timeOrigin ซึ่งจะมีความแม่นยําสูงขึ้น
  • 19 กุมภาพันธ์ 2021: เพิ่มหมายเหตุเกี่ยวกับนโยบายฟีเจอร์ allow="cross-origin-isolated" และฟังก์ชันการแก้ไขข้อบกพร่องในเครื่องมือสำหรับนักพัฒนาเว็บ
  • 15 ตุลาคม 2020: self.crossOriginIsolated พร้อมใช้งานใน Chrome 87 ซึ่ง document.domain จะเปลี่ยนแปลงไม่ได้เมื่อ self.crossOriginIsolated แสดงผล true performance.measureUserAgentSpecificMemory() จะสิ้นสุดช่วงทดลองใช้จากต้นทางและ จะเปิดใช้โดยค่าเริ่มต้นใน Chrome 89 Shared Array Buffer ใน Android Chrome จะพร้อมใช้งานจาก Chrome 88

โดย API ของเว็บบางอย่างจะเพิ่มความเสี่ยงในการโจมตีแบบ Side-channel อย่างเช่น Spectre เบราว์เซอร์จะเสนอสภาพแวดล้อมแยกต่างหากที่อิงจากการเลือกใช้ซึ่งเรียกว่าการแยกแบบข้ามต้นทางเพื่อลดความเสี่ยงดังกล่าว ด้วยสถานะแยกแบบข้ามต้นทาง หน้าเว็บจะสามารถใช้ฟีเจอร์พิเศษต่อไปนี้

API คำอธิบาย
SharedArrayBuffer ต้องระบุสำหรับชุดข้อความ WebAssembly มีให้บริการใน Android Chrome 88 ปัจจุบันเวอร์ชันเดสก์ท็อปจะเปิดใช้โดยค่าเริ่มต้นด้วยความช่วยเหลือจาก การแยกเว็บไซต์ แต่จะต้องใช้สถานะการแยกเว็บไซต์แบบข้ามต้นทางและ จะปิดใช้โดยค่าเริ่มต้นใน Chrome 92
performance.measureUserAgentSpecificMemory() พร้อมใช้งานใน Chrome 89
performance.now() performance.timeOrigin ซึ่งขณะนี้พร้อมให้บริการในเบราว์เซอร์ต่างๆ ที่มีความละเอียดจำกัดอยู่ที่ 100 ไมโครวินาทีขึ้นไป การแยกแบบข้ามต้นทางจะทำให้มีความละเอียดไม่เกิน 5 ไมโครวินาที
ฟีเจอร์ที่จะพร้อมใช้งานหลังสถานะแยกแบบข้ามต้นทาง

สถานะที่แยกแบบข้ามต้นทางยังป้องกันไม่ให้แก้ไข document.domain อีกด้วย (ความสามารถในการแก้ไข document.domain จะทำให้มีการสื่อสารระหว่างเอกสารที่อยู่ในเว็บไซต์เดียวกันและถือเป็นช่องโหว่ในนโยบายต้นทางเดียวกัน)

หากต้องการเลือกใช้สถานะแยกแบบข้ามต้นทาง คุณจะต้องส่งส่วนหัว HTTP ต่อไปนี้ในเอกสารหลัก

Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin

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

คุณตรวจสอบได้ว่าหน้าเว็บอยู่ในสถานะแยกต่างหากแบบข้ามต้นทางหรือไม่โดยการตรวจสอบ self.crossOriginIsolated

ซึ่งบทความนี้จะแสดงวิธีใช้ส่วนหัวใหม่ดังกล่าว ในบทความติดตาม ฉันจะให้ความเป็นมาและบริบทเพิ่มเติม

ทำให้ COOP และ COEP ใช้งานได้เพื่อแยกเว็บไซต์แบบข้ามต้นทาง

ผสานรวม COOP และ COEP

1. ตั้งค่าส่วนหัว Cross-Origin-Opener-Policy: same-origin ในเอกสารระดับบนสุด

เมื่อเปิดใช้ COOP: same-origin ในเอกสารระดับบนสุด หน้าต่างที่มีต้นทางเดียวกันและหน้าต่างที่เปิดจากเอกสารจะมีกลุ่มบริบทการท่องเว็บที่แยกต่างหาก เว้นแต่จะอยู่ในต้นทางเดียวกันที่มีการตั้งค่า COOP เดียวกัน ดังนั้น ระบบจะบังคับใช้การแยกสำหรับหน้าต่างที่เปิดอยู่และปิดใช้การสื่อสารร่วมกันระหว่างทั้ง 2 หน้าต่าง

กลุ่มบริบทในการท่องเว็บคือชุดหน้าต่างที่สามารถอ้างอิงถึงกันได้ เช่น เอกสารระดับบนสุดและเอกสารย่อยที่ฝังผ่าน <iframe> หากเว็บไซต์ (https://a.example) เปิดหน้าต่างป๊อปอัป (https://b.example) หน้าต่างที่เปิดอยู่และหน้าต่างป๊อปอัปใช้บริบทการท่องเว็บเดียวกัน จึงเข้าถึงได้ผ่าน DOM API เช่น window.opener

กลุ่มบริบทของการท่องเว็บ

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

2. ตรวจสอบว่าทรัพยากรเปิดใช้ CORP หรือ CORS

ตรวจสอบว่าทรัพยากรทั้งหมดในหน้าเว็บโหลดด้วยส่วนหัว HTTP ของ CORP หรือ CORS จำเป็นต้องมีขั้นตอนนี้สำหรับขั้นตอนที่ 4 การเปิดใช้ COEP

คุณต้องดำเนินการต่อไปนี้ ทั้งนี้ขึ้นอยู่กับลักษณะของทรัพยากร:

  • หากคาดว่าทรัพยากรจะโหลดจากต้นทางเดียวกันเท่านั้น ให้ตั้งค่าส่วนหัว Cross-Origin-Resource-Policy: same-origin
  • หากคาดว่าทรัพยากรจะโหลดจากเว็บไซต์เดียวกันเท่านั้นแต่ข้ามต้นทาง ให้ตั้งค่าส่วนหัว Cross-Origin-Resource-Policy: same-site
  • หากทรัพยากรโหลดจากแบบข้ามต้นทางภายใต้การควบคุมของคุณ ให้ตั้งค่าส่วนหัว Cross-Origin-Resource-Policy: cross-origin หากเป็นไปได้
  • สำหรับทรัพยากรข้ามต้นทางที่คุณไม่มีสิทธิ์ควบคุม ให้ทำดังนี้
    • ใช้แอตทริบิวต์ crossorigin ในแท็ก HTML สำหรับการโหลด หากทรัพยากรแสดงด้วย CORS (เช่น <img src="***" crossorigin>)
    • ขอให้เจ้าของแหล่งข้อมูลสนับสนุน CORS หรือ CORP
  • สำหรับ iframe ให้ทำตามหลักการเดียวกับข้างต้นและตั้งค่า Cross-Origin-Resource-Policy: cross-origin (หรือ same-site, same-origin ขึ้นอยู่กับบริบท)
  • สคริปต์ที่โหลดด้วย WebWorker ต้องแสดงจากต้นทางเดียวกัน คุณจึงไม่ต้องใช้ส่วนหัว CORP หรือ CORS
  • สำหรับเอกสารหรือผู้ปฏิบัติงานที่ให้บริการด้วย COEP: require-corp ทรัพยากรย่อยแบบข้ามต้นทางที่โหลดโดยไม่มี CORS ต้องตั้งค่าส่วนหัว Cross-Origin-Resource-Policy: cross-origin เพื่อให้เลือกใช้การฝังได้ เช่น นโยบายนี้มีผลกับ <script>, importScripts, <link>, <video>, <iframe> เป็นต้น

3. ใช้ส่วนหัว HTTP สำหรับรายงานเท่านั้นของ COEP เพื่อประเมินทรัพยากรที่ฝัง

ก่อนที่จะเปิดใช้ COEP โดยสมบูรณ์ คุณทดลองเรียกใช้ได้โดยใช้ส่วนหัว Cross-Origin-Embedder-Policy-Report-Only เพื่อตรวจสอบว่านโยบายใช้งานได้จริงหรือไม่ คุณจะได้รับรายงานโดยไม่บล็อกเนื้อหาที่ฝัง

นำวิธีนี้ไปใช้กับเอกสารทั้งหมด รวมถึงเอกสารระดับบนสุด, iframe และสคริปต์ของผู้ปฏิบัติงาน สำหรับข้อมูลเกี่ยวกับส่วนหัว HTTP สำหรับการรายงานเท่านั้น โปรดดูสังเกตปัญหาโดยใช้ Reporting API

4. เปิดใช้ COEP

เมื่อยืนยันแล้วว่าทุกอย่างทำงานได้และสามารถโหลดทรัพยากรทั้งหมดได้สำเร็จ ให้เปลี่ยนส่วนหัว Cross-Origin-Embedder-Policy-Report-Only เป็นส่วนหัว Cross-Origin-Embedder-Policy ที่มีค่าเดียวกันเป็นเอกสารทั้งหมด รวมถึงเอกสารที่ฝังผ่าน iframe และสคริปต์สำหรับผู้ปฏิบัติงาน

พิจารณาว่าการแยกสำเร็จด้วย self.crossOriginIsolated หรือไม่

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

แก้ปัญหาโดยใช้เครื่องมือสำหรับนักพัฒนาเว็บใน Chrome

สำหรับทรัพยากรที่แสดงผลบนหน้าจอ เช่น รูปภาพ การตรวจหาปัญหา COEP นั้นค่อนข้างง่ายเนื่องจากคำขอจะถูกบล็อกและหน้าเว็บจะระบุรูปภาพที่หายไป อย่างไรก็ตาม สำหรับทรัพยากรที่ไม่จำเป็นต้องมีภาพลักษณ์ เช่น สคริปต์หรือสไตล์ ปัญหาของ COEP อาจไม่มีใครสังเกตได้ ลองใช้แผง "เครือข่ายเครื่องมือสำหรับนักพัฒนาเว็บ" แทน หากเกิดปัญหากับ COEP คุณควรเห็น (blocked:NotSameOriginAfterDefaultedToSameOriginByCoep) ในคอลัมน์สถานะ

ปัญหา COEP ในคอลัมน์สถานะของแผงเครือข่าย

จากนั้นคุณสามารถคลิกที่รายการเพื่อดูรายละเอียดเพิ่มเติม

รายละเอียดของปัญหา COEP จะแสดงในแท็บส่วนหัวหลังจากคลิกทรัพยากรเครือข่ายในแผงเครือข่าย

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

คุณตรวจสอบสถานะของ iframe เช่น ความพร้อมใช้งานของ SharedArrayBuffer ฯลฯ ได้

เครื่องมือตรวจสอบ iframe ของเครื่องมือสําหรับนักพัฒนาเว็บใน Chrome

นอกจากนี้ คุณยังตรวจสอบสถานะของหน้าต่างป๊อปอัปได้ เช่น มีการแยกแบบข้ามต้นทางหรือไม่

เครื่องมือตรวจสอบหน้าต่างป๊อปอัปสำหรับเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome

สังเกตปัญหาโดยใช้ Reporting API

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

หากต้องการดูวิธีกำหนดค่า Reporting API และตั้งค่าเซิร์ฟเวอร์ให้รับรายงาน ให้ไปที่การใช้ Reporting API

ตัวอย่างรายงาน COEP

ตัวอย่างเพย์โหลดรายงาน COEP เมื่อบล็อกทรัพยากรแบบข้ามต้นทางจะมีลักษณะดังนี้

[{
  "age": 25101,
  "body": {
    "blocked-url": "https://third-party-test.glitch.me/check.svg?",
    "blockedURL": "https://third-party-test.glitch.me/check.svg?",
    "destination": "image",
    "disposition": "enforce",
    "type": "corp"
  },
  "type": "coep",
  "url": "https://cross-origin-isolation.glitch.me/?coep=require-corp&coop=same-origin&",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4249.0 Safari/537.36"
}]

ตัวอย่างรายงาน COOP

ตัวอย่างเพย์โหลดรายงาน COOP เมื่อมีการเปิดหน้าต่างป๊อปอัปแยกออกมาเป็นแบบนี้

[{
  "age": 7,
  "body": {
    "disposition": "enforce",
    "effectivePolicy": "same-origin",
    "nextResponseURL": "https://third-party-test.glitch.me/popup?report-only&coop=same-origin&",
    "type": "navigation-from-response"
  },
  "type": "coop",
  "url": "https://cross-origin-isolation.glitch.me/coop?coop=same-origin&",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4246.0 Safari/537.36"
}]

เมื่อกลุ่มบริบทในการท่องเว็บต่างๆ พยายามเข้าถึงกันและกัน (ในโหมด "รายงานเท่านั้น") COOP ก็ส่งรายงานด้วย เช่น รายงานเมื่อพยายามใช้ postMessage() จะมีลักษณะดังนี้

[{
  "age": 51785,
  "body": {
    "columnNumber": 18,
    "disposition": "reporting",
    "effectivePolicy": "same-origin",
    "lineNumber": 83,
    "property": "postMessage",
    "sourceFile": "https://cross-origin-isolation.glitch.me/popup.js",
    "type": "access-from-coop-page-to-openee"
  },
  "type": "coop",
  "url": "https://cross-origin-isolation.glitch.me/coop?report-only&coop=same-origin&",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4246.0 Safari/537.36"
},
{
  "age": 51785,
  "body": {
    "disposition": "reporting",
    "effectivePolicy": "same-origin",
    "property": "postMessage",
    "type": "access-to-coop-page-from-openee"
  },
  "type": "coop",
  "url": "https://cross-origin-isolation.glitch.me/coop?report-only&coop=same-origin&",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4246.0 Safari/537.36"
}]

บทสรุป

ใช้ส่วนหัว HTTP COOP และ COEP ร่วมกันเพื่อทำให้หน้าเว็บเป็นสถานะแยกแบบข้ามต้นทางแบบพิเศษ คุณจะตรวจสอบ self.crossOriginIsolated ได้เพื่อดูว่าหน้าเว็บอยู่ในสถานะแยกแบบข้ามต้นทางหรือไม่

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

แหล่งข้อมูล