Tại sao bạn cần tính năng "tách biệt nhiều nguồn gốc" để có được các tính năng mạnh mẽ

Tìm hiểu lý do tại sao cần phải tách biệt nhiều nguồn gốc để sử dụng các tính năng mạnh mẽ như SharedArrayBuffer, performance.measureUserAgentSpecificMemory() và bộ tính giờ có độ phân giải cao với độ chính xác cao hơn.

Giới thiệu

Trong bài viết Tạo trang web "bị tách biệt nhiều nguồn gốc" bằng COOP và COEP, chúng tôi đã giải thích cách chuyển sang trạng thái "tách biệt nhiều nguồn gốc" bằng COOP và COEP. Đây là bài viết đi kèm giải thích lý do tại sao cần phải tách biệt nhiều nguồn gốc để bật các tính năng mạnh mẽ trên trình duyệt.

Thông tin khái quát

Web được xây dựng dựa trên chính sách cùng nguồn gốc: một tính năng bảo mật hạn chế cách các tài liệu và tập lệnh có thể tương tác với tài nguyên từ một nguồn gốc khác. Nguyên tắc này hạn chế cách trang web có thể truy cập vào tài nguyên nhiều nguồn gốc. Ví dụ: tài liệu từ https://a.example bị chặn truy cập vào dữ liệu được lưu trữ tại https://b.example.

Tuy nhiên, chính sách cùng nguồn gốc có một số trường hợp ngoại lệ trước đây. Mọi trang web đều có thể:

  • Nhúng iframe nhiều nguồn gốc
  • Bao gồm các tài nguyên trên nhiều nguồn gốc như hình ảnh hoặc tập lệnh
  • Mở cửa sổ bật lên trên nhiều nguồn gốc có tham chiếu DOM

Nếu có thể thiết kế web từ đầu, các trường hợp ngoại lệ này sẽ không tồn tại. Thật không may, vào thời điểm cộng đồng web nhận ra những lợi ích chính của một chính sách nghiêm ngặt cùng nguồn gốc, web đã dựa vào các ngoại lệ này.

Những tác dụng phụ về bảo mật của chính sách yêu cầu phải có cùng nguồn gốc đã được khắc phục theo hai cách. Một cách là thông qua việc giới thiệu một giao thức mới có tên là Chia sẻ tài nguyên trên nhiều nguồn gốc (CORS) với mục đích đảm bảo rằng máy chủ cho phép chia sẻ tài nguyên có một nguồn gốc nhất định. Cách thứ hai là ngầm xoá quyền truy cập tập lệnh trực tiếp vào các tài nguyên nhiều nguồn gốc trong khi vẫn duy trì khả năng tương thích ngược. Các tài nguyên trên nhiều nguồn gốc như vậy được gọi là tài nguyên "không rõ ràng". Ví dụ: đây là lý do tại sao việc thao tác các pixel của hình ảnh nhiều nguồn gốc thông qua CanvasRenderingContext2D đều thất bại trừ phi CORS được áp dụng cho hình ảnh đó.

Tất cả các quyết định về chính sách này đều diễn ra trong một nhóm ngữ cảnh duyệt web.

Nhóm ngữ cảnh duyệt web

Trong một thời gian dài, sự kết hợp giữa CORS và tài nguyên mờ là đủ để đảm bảo an toàn cho các trình duyệt. Đôi khi, chúng tôi phát hiện thấy các trường hợp phức tạp (chẳng hạn như lỗ hổng JSON) và cần khắc phục, nhưng nhìn chung, nguyên tắc không cho phép quyền đọc trực tiếp vào các byte thô của tài nguyên trên nhiều nguồn gốc đã được khắc phục.

Tất cả điều này đã thay đổi với Spectre, khiến mọi dữ liệu được tải vào cùng một nhóm ngữ cảnh duyệt web là mã có thể đọc được. Bằng cách đo lường thời gian thực hiện một số thao tác nhất định, kẻ tấn công có thể đoán nội dung trong bộ nhớ đệm của CPU và qua đó, nội dung của bộ nhớ tiến trình. Các cuộc tấn công định thời như vậy có thể xảy ra với bộ tính giờ có độ chi tiết thấp trong nền tảng, nhưng có thể được tăng tốc bằng bộ tính giờ có độ chi tiết cao, cả rõ ràng (như performance.now()) và ngầm ẩn (như SharedArrayBuffer). Nếu evil.com nhúng một hình ảnh nhiều nguồn gốc, thì chúng có thể sử dụng cuộc tấn công Spectre để đọc dữ liệu pixel của hình ảnh đó. Điều này khiến các biện pháp bảo vệ dựa trên "độ mờ" trở nên không hiệu quả.

Quang phổ

Tốt nhất là máy chủ sở hữu tài nguyên phải xét duyệt rõ ràng tất cả các yêu cầu trên nhiều nguồn gốc. Nếu máy chủ sở hữu tài nguyên không cung cấp quá trình rà soát, thì dữ liệu sẽ không bao giờ được đưa vào nhóm ngữ cảnh duyệt web của đối tượng xấu, do đó sẽ không vượt qua được các cuộc tấn công Spectre mà trang web có thể thực hiện. Chúng tôi gọi đó là trạng thái tách biệt nhiều nguồn gốc. Đây chính xác là mục đích của COOP+COEP.

Ở trạng thái tách biệt nhiều nguồn gốc, trang web yêu cầu được coi là ít nguy hiểm hơn và điều này mở khoá các tính năng mạnh mẽ như SharedArrayBuffer, performance.measureUserAgentSpecificMemory()bộ tính giờ độ phân giải cao với độ chính xác cao hơn, nếu không có thể dùng cho các cuộc tấn công giống như Spectre. Điều này cũng ngăn việc sửa đổi document.domain.

Chính sách đối với trình nhúng trên nhiều nguồn gốc

Chính sách về trình nhúng trên nhiều nguồn gốc (COEP) ngăn chặn một tài liệu tải mọi tài nguyên trên nhiều nguồn gốc không cấp quyền rõ ràng cho tài liệu (sử dụng CORP hoặc CORS). Với tính năng này, bạn có thể khai báo rằng một tài liệu không thể tải các tài nguyên như vậy.

Cách hoạt động của COEP

Để kích hoạt chính sách này, hãy thêm tiêu đề HTTP sau đây vào tài liệu:

Cross-Origin-Embedder-Policy: require-corp

Từ khoá require-corp là giá trị duy nhất được chấp nhận cho COEP. Việc này sẽ thực thi chính sách rằng tài liệu chỉ có thể tải các tài nguyên có cùng nguồn gốc hoặc các tài nguyên được đánh dấu rõ ràng là có thể tải từ một nguồn gốc khác.

Để tài nguyên có thể tải từ một nguồn gốc khác, chúng cần hỗ trợ tính năng Chia sẻ tài nguyên trên nhiều nguồn gốc (CORS) hoặc Chính sách tài nguyên trên nhiều nguồn gốc (CORP).

Chia sẻ tài nguyên trên nhiều nguồn gốc

Nếu một tài nguyên nhiều nguồn gốc hỗ trợ tính năng Chia sẻ tài nguyên trên nhiều nguồn gốc (CORS), bạn có thể sử dụng thuộc tính crossorigin để tải thuộc tính đó vào trang web của mình mà không bị COEP chặn.

<img src="https://third-party.example.com/image.jpg" crossorigin>

Ví dụ: nếu tài nguyên hình ảnh này được phân phát cùng với tiêu đề CORS, hãy sử dụng thuộc tính crossorigin để yêu cầu tìm nạp tài nguyên sẽ sử dụng chế độ CORS. Thao tác này cũng ngăn hình ảnh tải được trừ phi đặt tiêu đề CORS.

Tương tự, bạn có thể tìm nạp dữ liệu trên nhiều nguồn gốc thông qua phương thức fetch() mà không cần phải xử lý đặc biệt, miễn là máy chủ phản hồi bằng các tiêu đề HTTP phù hợp.

Chính sách về tài nguyên trên nhiều nguồn gốc

Ban đầu, Chính sách tài nguyên trên nhiều nguồn gốc (CORP) được giới thiệu dưới dạng một phương thức chọn sử dụng nhằm bảo vệ tài nguyên của bạn không bị tải từ một nguồn gốc khác. Trong trường hợp COEP, CORP có thể chỉ định chính sách của chủ sở hữu tài nguyên về người có thể tải tài nguyên.

Tiêu đề Cross-Origin-Resource-Policy có thể có ba giá trị:

Cross-Origin-Resource-Policy: same-site

Các tài nguyên được đánh dấu là same-site chỉ có thể được tải từ cùng một trang web.

Cross-Origin-Resource-Policy: same-origin

Các tài nguyên được đánh dấu là same-origin chỉ có thể tải từ cùng một nguồn gốc.

Cross-Origin-Resource-Policy: cross-origin

Bất kỳ trang web nào cũng có thể tải các tài nguyên được đánh dấu là cross-origin. (Giá trị này đã được thêm vào thông số kỹ thuật CORP cùng với COEP.)

Chính sách về tiện ích mở trên nhiều nguồn gốc

Chính sách về trình mở nhiều nguồn gốc (COOP) cho phép bạn đảm bảo rằng cửa sổ cấp cao nhất được tách biệt với các tài liệu khác bằng cách đặt các tài liệu đó vào một nhóm ngữ cảnh duyệt web khác để chúng không thể tương tác trực tiếp với cửa sổ cấp cao nhất. Ví dụ: nếu một tài liệu có COOP mở cửa sổ bật lên, thì thuộc tính window.opener của tài liệu đó sẽ là null. Ngoài ra, thuộc tính .closed của tham chiếu đến trình mở sẽ trả về true.

COOP

Tiêu đề Cross-Origin-Opener-Policy có thể có ba giá trị:

Cross-Origin-Opener-Policy: same-origin

Các tài liệu được đánh dấu là same-origin có thể chia sẻ cùng một nhóm ngữ cảnh duyệt web với các tài liệu có cùng nguồn gốc và được đánh dấu rõ ràng là same-origin.

COOP

Cross-Origin-Opener-Policy: same-origin-allow-popups

Tài liệu cấp cao nhất có same-origin-allow-popups sẽ giữ lại thông tin tham chiếu đến mọi cửa sổ bật lên mà không thiết lập COOP hoặc chọn không tách biệt bằng cách thiết lập COOP của unsafe-none.

COOP

Cross-Origin-Opener-Policy: unsafe-none

unsafe-none là tuỳ chọn mặc định và cho phép thêm tài liệu vào nhóm ngữ cảnh duyệt web của trình mở, trừ phi chính trình mở có COOP là same-origin.

Tóm tắt

Nếu bạn muốn đảm bảo quyền truy cập vào các tính năng mạnh mẽ như SharedArrayBuffer, performance.measureUserAgentSpecificMemory() hoặc bộ hẹn giờ có độ phân giải cao với độ chính xác cao hơn, hãy nhớ rằng tài liệu của bạn cần sử dụng cả COEP với giá trị require-corp và COOP với giá trị same-origin. Trong trường hợp không có một trong hai, trình duyệt sẽ không đảm bảo khả năng tách biệt đủ để bật các tính năng mạnh mẽ đó một cách an toàn. Bạn có thể xác định tình huống của trang bằng cách kiểm tra xem self.crossOriginIsolated có trả về true hay không.

Tìm hiểu các bước để triển khai việc này trong bài viết Làm cho trang web của bạn "bị tách biệt nhiều nguồn gốc" bằng cách sử dụng COOP và COEP.

Tài nguyên