Tách biệt trang web cho nhà phát triển web

Chrome 67 trên máy tính có một tính năng mới có tên là Tách biệt trang web được bật theo mặc định. Bài viết này giải thích về tính năng Cách ly trang web, lý do cần thiết và lý do nhà phát triển web nên lưu ý đến tính năng này.

Cách ly trang web là gì?

Internet là nơi để xem video về mèo và quản lý ví tiền mã hoá, cùng nhiều thứ khác — nhưng bạn không muốn fluffycats.example có quyền truy cập vào những đồng tiền mã hoá quý giá của mình! May mắn thay, các trang web thường không thể truy cập vào dữ liệu của nhau bên trong trình duyệt nhờ Chính sách về cùng một nguồn gốc. Tuy nhiên, các trang web độc hại có thể tìm cách bỏ qua chính sách này để tấn công các trang web khác và đôi khi, các lỗi bảo mật được tìm thấy trong mã trình duyệt thực thi Chính sách cùng nguồn gốc. Nhóm Chrome sẽ cố gắng khắc phục các lỗi như vậy nhanh nhất có thể.

Tính năng Tách biệt trang web là một tính năng bảo mật trong Chrome, cung cấp thêm một lớp phòng thủ để giảm khả năng thành công của các cuộc tấn công như vậy. Tính năng này đảm bảo rằng các trang từ các trang web khác nhau luôn được đưa vào các quy trình khác nhau, mỗi quy trình chạy trong một hộp cát giới hạn những việc mà quy trình được phép làm. Tính năng này cũng chặn quy trình nhận một số loại dữ liệu nhạy cảm nhất định từ các trang web khác. Do đó, với tính năng Cách ly trang web, một trang web độc hại sẽ gặp khó khăn hơn nhiều khi sử dụng các cuộc tấn công kênh bên đầu cơ như Spectre để lấy cắp dữ liệu từ các trang web khác. Khi nhóm Chrome hoàn tất các biện pháp thực thi bổ sung, tính năng Tách biệt trang web cũng sẽ hữu ích ngay cả khi trang của kẻ tấn công có thể vi phạm một số quy tắc trong quy trình của chính trang đó.

Tính năng Cách ly trang web giúp các trang web không đáng tin cậy khó truy cập hoặc đánh cắp thông tin từ tài khoản của bạn trên các trang web khác. Tính năng này tăng cường bảo vệ trước nhiều loại lỗi bảo mật, chẳng hạn như các cuộc tấn công kênh bên Meltdown và Spectre gần đây.

Để biết thêm thông tin chi tiết về tính năng Tách biệt trang web, hãy xem bài viết của chúng tôi trên blog Bảo mật của Google.

Chặn đọc trên nhiều nguồn gốc

Ngay cả khi tất cả các trang trên nhiều trang web được đưa vào những quy trình riêng biệt, các trang vẫn có thể yêu cầu hợp pháp một số tài nguyên phụ trên nhiều trang web, chẳng hạn như hình ảnh và JavaScript. Một trang web độc hại có thể sử dụng phần tử <img> để tải tệp JSON chứa dữ liệu nhạy cảm, chẳng hạn như số dư tài khoản ngân hàng của bạn:

<img src="https://your-bank.example/balance.json" />
<!-- Note: the attacker refused to add an `alt` attribute, for extra evil points. -->

Nếu không có tính năng Cách ly trang web, nội dung của tệp JSON sẽ được đưa vào bộ nhớ của quy trình trình kết xuất. Tại thời điểm đó, trình kết xuất sẽ nhận thấy rằng đó không phải là định dạng hình ảnh hợp lệ và không hiển thị hình ảnh. Tuy nhiên, sau đó, kẻ tấn công có thể khai thác một lỗ hổng như Spectre để có thể đọc khối bộ nhớ đó.

Thay vì sử dụng <img>, kẻ tấn công cũng có thể sử dụng <script> để ghi dữ liệu nhạy cảm vào bộ nhớ:

<script src="https://your-bank.example/balance.json"></script>

Tính năng Chặn đọc trên nhiều nguồn gốc (CORB) là một tính năng bảo mật mới giúp ngăn nội dung của balance.json xâm nhập vào bộ nhớ của quy trình kết xuất dựa trên loại MIME của nội dung đó.

Hãy cùng tìm hiểu cách hoạt động của CORB. Một trang web có thể yêu cầu hai loại tài nguyên từ máy chủ:

  1. tài nguyên dữ liệu chẳng hạn như tài liệu HTML, XML hoặc JSON
  2. tài nguyên đa phương tiện như hình ảnh, JavaScript, CSS hoặc phông chữ

Một trang web có thể nhận tài nguyên dữ liệu từ nguồn gốc của chính trang web đó hoặc từ các nguồn gốc khác bằng các tiêu đề CORS cho phép, chẳng hạn như Access-Control-Allow-Origin: *. Mặt khác, bạn có thể đưa tài nguyên phương tiện vào từ bất kỳ nguồn gốc nào, ngay cả khi không có tiêu đề CORS cho phép.

CORB ngăn quá trình kết xuất nhận tài nguyên dữ liệu trên nhiều nguồn gốc (tức là HTML, XML hoặc JSON) nếu:

  • tài nguyên có tiêu đề X-Content-Type-Options: nosniff
  • CORS không cho phép truy cập vào tài nguyên một cách rõ ràng

Nếu tài nguyên dữ liệu trên nhiều nguồn gốc không có bộ tiêu đề X-Content-Type-Options: nosniff, thì CORB sẽ cố gắng theo dõi nội dung phản hồi để xác định xem đó là HTML, XML hay JSON. Điều này là cần thiết vì một số máy chủ web được định cấu hình không chính xác và phân phát hình ảnh dưới dạng text/html, chẳng hạn.

Các tài nguyên dữ liệu bị chính sách CORB chặn sẽ được trình bày cho quy trình dưới dạng trống, mặc dù yêu cầu vẫn diễn ra ở chế độ nền. Do đó, trang web độc hại sẽ gặp khó khăn khi lấy dữ liệu trên nhiều trang web vào quy trình lấy cắp.

Để được bảo mật tối ưu và nhận được lợi ích từ CORB, bạn nên thực hiện những việc sau:

  • Đánh dấu các phản hồi bằng tiêu đề Content-Type chính xác. (Ví dụ: tài nguyên HTML phải được phân phát dưới dạng text/html, tài nguyên JSON có loại MIME JSON và tài nguyên XML có loại MIME XML).
  • Chọn không sử dụng tính năng đánh hơi bằng cách sử dụng tiêu đề X-Content-Type-Options: nosniff. Nếu không có tiêu đề này, Chrome sẽ phân tích nhanh nội dung để cố gắng xác nhận rằng loại nội dung đó là chính xác. Tuy nhiên, vì lỗi này xảy ra khi cho phép các phản hồi đi qua để tránh chặn các tệp như JavaScript, bạn nên tự xác nhận việc làm đúng.

Để biết thêm thông tin, hãy tham khảo bài viết về CORB dành cho nhà phát triển web hoặc nội dung giải thích chuyên sâu của chúng tôi về CORB.

Tại sao nhà phát triển web nên quan tâm đến tính năng Tách biệt trang web?

Trong hầu hết trường hợp, tính năng Cách ly trang web là một tính năng trình duyệt ở chế độ nền mà các nhà phát triển web không trực tiếp tiếp cận được. Ví dụ: không có API mới nào được hiển thị trên web để tìm hiểu. Nhìn chung, các trang web sẽ không thể phân biệt được khi chạy có hoặc không có tính năng Cách ly trang web.

Tuy nhiên, vẫn có một số ngoại lệ đối với quy tắc này. Việc bật tính năng Cách ly trang web sẽ có một số tác dụng phụ nhỏ có thể ảnh hưởng đến trang web của bạn. Chúng tôi duy trì danh sách các vấn đề đã biết về tính năng Cách ly trang web và trình bày chi tiết về những vấn đề quan trọng nhất ở bên dưới.

Bố cục toàn trang không còn đồng bộ nữa

Với tính năng Cách ly trang web, bố cục toàn trang không còn được đảm bảo là đồng bộ nữa vì các khung của một trang hiện có thể được phân bổ trên nhiều quy trình. Điều này có thể ảnh hưởng đến các trang nếu chúng giả định rằng thay đổi về bố cục sẽ ngay lập tức truyền đến tất cả khung trên trang.

Ví dụ: hãy xem xét một trang web có tên fluffykittens.example giao tiếp với một tiện ích mạng xã hội được lưu trữ trên social-widget.example:

<!-- https://fluffykittens.example/ -->
<iframe src="https://social-widget.example/" width="123"></iframe>
<script>
  const iframe = document.querySelector('iframe');
  iframe.width = 456;
  iframe.contentWindow.postMessage(
    // The message to send:
    'Meow!',
    // The target origin:
    'https://social-widget.example'
  );
</script>

Ban đầu, chiều rộng của <iframe> của tiện ích mạng xã hội là 123 pixel. Tuy nhiên, trang FluffyKittens sẽ thay đổi chiều rộng thành 456 pixel (kích hoạt bố cục) và gửi thông báo đến tiện ích mạng xã hội có mã sau:

<!-- https://social-widget.example/ -->
<script>
  self.onmessage = () => {
    console.log(document.documentElement.clientWidth);
  };
</script>

Bất cứ khi nào tiện ích mạng xã hội nhận được thông báo thông qua API postMessage, tiện ích này sẽ ghi lại chiều rộng của phần tử <html> gốc.

Giá trị chiều rộng nào được ghi lại? Trước khi Chrome bật tính năng Tách biệt trang web, câu trả lời là 456. Việc truy cập vào document.documentElement.clientWidth sẽ buộc bố cục, bố cục này từng đồng bộ trước khi Chrome bật tính năng Cách ly trang web. Tuy nhiên, khi tính năng Cách ly trang web đang bật, việc bố cục lại tiện ích mạng xã hội trên nhiều nguồn gốc giờ đây sẽ diễn ra không đồng bộ trong một quy trình riêng. Do đó, câu trả lời hiện cũng có thể là 123, tức là giá trị width cũ.

Nếu một trang thay đổi kích thước của <iframe> trên nhiều nguồn gốc rồi gửi postMessage đến trang đó, thì với tính năng Cách ly trang web, khung nhận có thể chưa biết kích thước mới của trang khi nhận được thông báo. Nói chung, điều này có thể làm hỏng các trang nếu các trang giả định rằng một thay đổi về bố cục sẽ ngay lập tức được truyền đến tất cả các khung trên trang.

Trong ví dụ cụ thể này, một giải pháp mạnh mẽ hơn sẽ đặt width trong khung mẹ và phát hiện sự thay đổi đó trong <iframe> bằng cách theo dõi sự kiện resize.

Trình xử lý huỷ tải có thể hết thời gian chờ thường xuyên hơn

Khi một khung điều hướng hoặc đóng, tài liệu cũ cũng như mọi tài liệu khung con được nhúng trong đó đều chạy trình xử lý unload. Nếu hoạt động điều hướng mới diễn ra trong cùng một quy trình kết xuất đồ hoạ (ví dụ: điều hướng cùng nguồn gốc), thì các trình xử lý unload của tài liệu cũ và khung phụ của tài liệu đó có thể chạy tuỳ ý trong một thời gian dài trước khi cho phép xác nhận quy trình điều hướng mới.

addEventListener('unload', () => {
  doSomethingThatMightTakeALongTime();
});

Trong trường hợp này, trình xử lý unload trong tất cả khung hình đều rất đáng tin cậy.

Tuy nhiên, ngay cả khi không có tính năng Tách biệt trang web, một số thao tác điều hướng khung chính vẫn diễn ra trên nhiều quy trình, điều này ảnh hưởng đến hành vi của trình xử lý huỷ tải. Ví dụ: nếu bạn điều hướng từ old.example đến new.example bằng cách nhập URL vào thanh địa chỉ, thì thao tác điều hướng new.example sẽ diễn ra trong một quy trình mới. Trình xử lý tải xuống cho old.example và các khung con của trình xử lý này chạy trong quy trình old.example ở chế độ nền, sau khi trang new.example hiển thị và các trình xử lý tải xuống cũ sẽ bị chấm dứt nếu không hoàn tất trong một khoảng thời gian chờ nhất định. Vì trình xử lý giải phóng có thể không hoàn tất trước khi hết thời gian chờ, nên hành vi giải phóng sẽ kém tin cậy hơn.

Với tính năng Tách biệt trang web, tất cả thao tác điều hướng trên nhiều trang web sẽ trở thành thao tác trên nhiều quy trình, nhờ đó, các tài liệu trên nhiều trang web sẽ không chia sẻ quy trình với nhau. Do đó, trường hợp trên áp dụng trong nhiều trường hợp hơn và việc huỷ tải trình xử lý trong <iframe> thường có các hành vi chạy ở chế độ nền và hết thời gian chờ như mô tả ở trên.

Một điểm khác biệt khác do tính năng Cách ly trang web mang lại là thứ tự song song mới của trình xử lý tải xuống: nếu không có tính năng Cách ly trang web, trình xử lý tải xuống sẽ chạy theo thứ tự nghiêm ngặt từ trên xuống trên các khung. Tuy nhiên, với tính năng Cách ly trang web, các trình xử lý huỷ tải sẽ chạy song song trên nhiều quy trình.

Đây là những hậu quả cơ bản của việc bật tính năng Tách biệt trang web. Nhóm Chrome đang nỗ lực cải thiện độ tin cậy của trình xử lý giải phóng tải cho các trường hợp sử dụng phổ biến (nếu có thể). Chúng tôi cũng nhận thấy một số lỗi trong đó trình xử lý tải khung con chưa thể sử dụng một số tính năng nhất định và đang nỗ lực để giải quyết các lỗi đó.

Một trường hợp quan trọng đối với trình xử lý huỷ tải là gửi ping kết thúc phiên. Bạn thường làm như sau:

addEventListener('pagehide', () => {
  const image = new Image();
  img.src = '/end-of-session';
});

Do thay đổi này, có một phương pháp hiệu quả hơn và hiệu quả hơn là sử dụng navigator.sendBeacon:

addEventListener('pagehide', () => {
  navigator.sendBeacon('/end-of-session');
});

Nếu cần kiểm soát nhiều hơn đối với yêu cầu, bạn có thể sử dụng tuỳ chọn keepalive của API Tìm nạp:

addEventListener('pagehide', () => {
  fetch('/end-of-session', {keepalive: true});
});

Kết luận

Tính năng Tách biệt trang web giúp các trang web không đáng tin cậy khó truy cập hoặc đánh cắp thông tin từ tài khoản của bạn trên các trang web khác bằng cách tách riêng từng trang web thành một quy trình riêng. Trong đó, CORB cố gắng loại bỏ các tài nguyên dữ liệu nhạy cảm khỏi quy trình kết xuất. Các đề xuất ở trên đảm bảo bạn khai thác tối đa các tính năng bảo mật mới này.

Cảm ơn Alex Moshchuk, Charlie Reis, Jason Miller, Nasko Oskov, Philip Walton, Shubhi Panicker và Thomas Steiner đã đọc bản nháp của bài viết này và đưa ra ý kiến phản hồi.