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 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ộ 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 Tạo trang web "được phân tách nhiều nguồn gốc" bằng COOP và COEP, chúng tôi đã giải thích cách áp dụng trạng thái "được phân tách nhiều nguồn gốc" bằng COOP và COEP. Đây là bài viết đồng hành giải thích lý do 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 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 bị ngă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ố ngoại lệ trước đây. 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 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 bằng tệp tham chiếu DOM

Nếu có thể thiết kế web từ đầu, thì các 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 các 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 các trường hợp ngoại lệ này.

Các hiệu ứng phụ 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. Một cách khác là ngầm xoá quyền truy cập trực tiếp của tập lệnh vào 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 gốc như vậy được gọi là tài nguyên "mờ". 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 sẽ không thành công trừ phi bạn áp dụng CORS cho hình ảnh đó.

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

Nhóm bối cảnh duyệt web

Trong một thời gian dài, việc kết hợp CORS và tài nguyên mờ đã đủ để đảm bảo an toàn cho trình duyệt. Đôi khi, các trường hợp hiếm gặp (chẳng hạn như lỗ hổng 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 đọc trực tiếp vào các byte thô của tài nguyên đa nguồn gốc đã thành công.

Tất cả điều này đã thay đổi với Spectre, giúp mọi dữ liệu được tải vào cùng một nhóm ngữ cảnh duyệt web với mã của bạn 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 được nội dung của bộ nhớ đệm CPU và thông qua đó, nội dung của bộ nhớ của quy trình. Các cuộc tấn công theo thời gian như vậy có thể xảy ra với bộ hẹn giờ có độ chi tiết thấp tồn tại trong nền tảng, nhưng có thể được tăng tốc bằng bộ hẹn 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 trên nhiều nguồn gốc, thì kẻ tấn công có thể sử 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 trên "mức độ mờ" trở nên không hiệu quả.

Spectr

Lý tưởng nhất là tất cả các yêu cầu trên nhiều nguồn gốc 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ờ lọt vào nhóm ngữ cảnh duyệt web của một tác nhân độc hại, do đó sẽ nằm ngoài tầm tấn công của mọi 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 trên nhiều nguồn gốc. Đây chính là nội dung 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ở ra các tính năng mạnh mẽ như SharedArrayBuffer, performance.measureUserAgentSpecificMemory()trình 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 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 tài liệu tải bất kỳ tài nguyên nào trên nhiều nguồn gốc không cấp quyền tài liệu một cách rõ ràng (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 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. Đ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, tài nguyên đó 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 về 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 trê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), thì bạn có thể sử dụng thuộc tính crossorigin để tải tài nguyên đó vào trang web 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ừ khi 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 gốc 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 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

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 để bảo vệ tài nguyên của bạn khỏi bị tải bởi một nguồn gốc khác. Trong ngữ cảnh của 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ó ba 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 là 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 là same-origin từ cùng một nguồn gốc.

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 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ề trình mở trên nhiều nguồn gốc

Chính sách trình mở trên 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 để các tài liệu đó 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 đó 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 cũng đượ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 giữ lại các tệp tham chiếu đến bất kỳ cửa sổ bật lên nào 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 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 trình 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 mình cần sử dụng cả COEP với giá trị require-corp và COOP với giá trị same-origin. Nếu 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 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 trong bài viết Tạo trang web "được phân tách giữa các nguồn gốc" bằng cách sử dụng COOP và COEP.

Tài nguyên