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 cần có chế độ 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ộ hẹn 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 Đưa trang web của bạn vào trạng thái "được cách ly trên nhiều nguồn" bằng COOP và COEP, chúng tôi đã giải thích cách chuyển sang trạng thái "được cách ly trên nhiều nguồn" bằng COOP và COEP. Đây là bài viết bổ sung giải thích lý do cần có tính năng 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 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ác cách mà trang web có thể truy cập vào tài nguyên trên nhiều nguồn gốc. Ví dụ: một tài liệu từ https://a.example không được phép 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 từng có một số ngoại lệ. Mọi trang web đều có thể:

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

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

Các tác dụng phụ về bảo mật của chính sách cùng nguồn gốc lỏng lẻo như vậy đã được vá 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). Mục đích của giao thức này là đảm bảo rằng máy chủ cho phép chia sẻ tài nguyên với một nguồn gốc nhất định. Cách khác là xoá ngầm quyền truy cập trực tiếp vào tập lệnh đối với các tài nguyên trên nhiều nguồn gốc trong khi vẫn duy trì khả năng tương thích ngược. Những tài nguyên trên nhiều nguồn như vậy được gọi là tài nguyên "không trong suốt". Ví dụ: đây là lý do khiến việc thao tác các pixel của hình ảnh nhiều nguồn gốc thông qua CanvasRenderingContext2D không thành công, 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 bối cảnh duyệt web.

Nhóm bối 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à đủ để giúp trình duyệt an toàn. Đôi khi, các trường hợp đặc biệt (chẳng hạn như lỗ hổng bảo mật JSON) được phát hiện và cần được vá, nhưng nhìn chung, nguyên tắc không cho phép quyền truy cập đọ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 đã thành công.

Mọi thứ đã thay đổi với Spectre. Spectre có thể đọc mọi dữ liệu được tải vào cùng một nhóm bối cảnh duyệt web như mã của bạn. Bằng cách đo 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 được nội dung của bộ nhớ đệm CPU và thông qua đó, nội dung của bộ nhớ quy trình. Các cuộc tấn công định thời như vậy có thể xảy ra với các bộ hẹn giờ có độ chi tiết thấp có trong nền tảng, nhưng có thể được tăng tốc bằng các bộ hẹn giờ có độ chi tiết cao, cả bộ hẹn giờ rõ ràng (chẳng hạn như performance.now()) và bộ hẹn giờ ngầm (chẳng hạn như SharedArrayBuffer). Nếu evil.com nhúng một hình ảnh từ nhiều nguồn, họ có thể dùng một cuộc tấn công Spectre để đọc dữ liệu pixel của hình ảnh đó, khiến các biện pháp bảo vệ dựa vào "độ mờ" không hiệu quả.

Spectr

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

Trong trạng thái biệt lập trên 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ở ra các tính năng mạnh mẽ như SharedArrayBuffer, performance.measureUserAgentSpecificMemory()bộ hẹn giờ có độ phân giải cao với độ chính xác cao hơn. Nếu không, các tính năng này có thể được dùng cho các cuộc tấn công tương tự như Spectre. Điều này cũng ngăn chặ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 đối với trình nhúng trên nhiều nguồn gốc (COEP) ngăn một tài liệu tải bất kỳ tài nguyên trên nhiều nguồn gốc nào không cấp quyền rõ ràng cho tài liệu (bằng cách 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 đó.

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 vào tài liệu:

Cross-Origin-Embedder-Policy: require-corp

COEP nhận một giá trị duy nhất là require-corp. Điều này thực thi chính sách rằng tài liệu chỉ có thể tải tài nguyên từ cùng một nguồn gốc hoặ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.

Để có thể tải tài nguyên từ một nguồn gốc khác, các tài nguyên đó cần hỗ trợ Chia sẻ tài nguyên trên nhiều nguồn gốc (CORS) hoặc Chính sách về tài nguyê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 trên nhiều nguồn gốc hỗ trợ 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 tài nguyên đó 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 bằng 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. Điều này cũng ngăn hình ảnh tải trừ phi hình ảnh đó đặt tiêu đề CORS.

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

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

Chính sách tài nguyên trên nhiều nguồn gốc (CORP) ban đầu được giới thiệu dưới dạng một lựa chọn không bắt buộc để bảo vệ tài nguyên của bạn khỏi bị một nguồn gốc khác tải. Trong bối cảnh COEP, CORP có thể chỉ định chính sách của chủ sở hữu tài nguyên về những người có thể tải tài nguyên.

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

Cross-Origin-Resource-Policy: same-site

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

Cross-Origin-Resource-Policy: same-origin

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

Cross-Origin-Resource-Policy: cross-origin

Mọi trang web đều có thể tải các tài nguyên được đánh dấu cross-origin. (Giá trị này đã được thêm vào quy cách CORP cùng với COEP.)

Cross Origin Opener Policy

Chính sách Cross Origin Opener Policy (COOP) giú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 chúng vào một nhóm bối 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ở một 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 của trình mở đến thuộc tính này sẽ trả về true.

COOP

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

Cross-Origin-Opener-Policy: same-origin

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

COOP

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

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

COOP

Cross-Origin-Opener-Policy: unsafe-none

unsafe-none là giá trị 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 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, bạn chỉ cần nhớ rằng tài liệu của bạn cần sử dụng cả COEP có giá trị là require-corp và COOP có giá trị là same-origin. Nếu không có một trong hai, trình duyệt sẽ không đảm bảo đủ khả năng cách ly để bật an toàn các tính năng mạnh mẽ đó. Bạn có thể xác định tình trạ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 tại Cách làm cho trang web của bạn "được cách ly trên nhiều nguồn" bằng COOP và COEP.

Tài nguyên