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 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 khái niệm của tính năng Tách biệt trang web, lý do tính năng này cần thiết và lý do mà các nhà phát triển web nên lưu ý đến tính năng này.

Tách biệt trang web là gì?

Internet là để xem video về mèo và quản lý ví tiền mã hoá, cùng nhiều việc khác — nhưng bạn sẽ không muốn fluffycats.example truy cập được vào các đồng tiền mã hoá quý giá của mình! May mắn là 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 cùng 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, người dùng sẽ tìm thấy lỗi bảo mật trong mã trình duyệt thực thi Chính sách cùng nguồn gốc. Nhóm Chrome mong muốn khắc phục các lỗi như vậy nhanh nhất có thể.

Cách ly trang web là một tính năng bảo mật trong Chrome, cung cấp thêm một hàng phòng ngự để giảm khả năng thành công của các cuộc tấn công như vậy. Phương thức này đảm bảo 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. Ngoài ra, quy trình này cũng chặ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 Tách biệt trang web, trang web độc hại sẽ khó sử dụng các cuộc tấn công kênh bên theo suy đoán như Spectre để lấy cắp dữ liệu từ các trang web khác. Khi nhóm Chrome hoàn thành các biện pháp thực thi bổ sung, tính năng Cách ly 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 theo quy trình riêng.

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 lấy cắp thông tin trong tài khoản của bạn trên các trang web khác một cách hiệu quả hơn. Tính năng này giúp 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 về Google Security.

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 các quy trình riêng biệt, các trang vẫn có thể yêu cầu một cách 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. 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ư 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 Tách biệt trang web, nội dung của tệp JSON sẽ được đưa vào bộ nhớ của quá trình kết xuất. Tại thời điểm đó, trình kết xuất nhận thấy rằng đây 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 phần bộ nhớ đó.

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

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

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 trình kết xuất xử lý bộ nhớ dựa trên loại MIME.

Hãy cùng phân tích 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 như tài liệu HTML, XML hoặc JSON
  2. tài nguyên nội dung đa phương tiện như hình ảnh, JavaScript, CSS hoặc phông chữ

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

CORB ngăn không cho quá trình kết xuất nhận được tài nguyên dữ liệu trên nhiều nguồn gốc (ví dụ: 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 quyền 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 nhiều nguồn gốc chưa đặt tiêu đề X-Content-Type-Options: nosniff, thì CORB sẽ cố gắng nhận dạng 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 bị định cấu hình sai 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ẽ hiển thị 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 trong việc kéo dữ liệu trên nhiều trang web vào quy trình của mình để đánh cắp.

Để bảo mật tối ưu và hưởng lợi từ CORB, bạn nên:

  • Đánh dấu câu trả lờ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 với loại MIME JSON và tài nguyên XML với loại MIME XML).
  • Chọn không sử dụng tính năng nhận dạng 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ẽ tiến hành phân tích nhanh nội dung để cố gắng xác nhận rằng loại này là chính xác. Tuy nhiên, vì điều này xảy ra do lỗi trong việc cho phép phản hồi tránh chặn những thứ như tệp JavaScript, nên tốt hơn là bạn nên tự mình 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 phần 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ách biệt trang web là một tính năng ngầm định của trình duyệt, không hiển thị trực tiếp cho nhà phát triển web. Chẳng hạn như không có API hiển thị trên web mới. Nhìn chung, các trang web không được phân biệt được sự khác biệt khi chạy cùng với tính năng Cách ly trang web.

Tuy nhiên, quy tắc này có một số ngoại lệ. Việc bật tính năng Tách biệt trang web sẽ đi kèm với một số tác dụng phụ 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ề việc Tách biệt trang web và trình bày chi tiết 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 Tách biệt trang web, bố cục toàn trang không còn đảm bảo tính đồng bộ nữa, vì khung của một trang hiện có thể trải rộng trên nhiều quy trình. Điều này có thể ảnh hưởng đến 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 áp dụng cho tất cả các khung trên trang.

Ví dụ: hãy cùng xem xét một trang web có tên là fluffykittens.example giao tiếp với một tiện ích 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>

Lúc đầu, chiều rộng của <iframe> của tiện ích xã hội là 123 pixel. Tuy nhiên, sau đó, trang FluffyKittens thay đổi chiều rộng thành 456 pixel (kích hoạt bố cục) và gửi thông báo tới 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 xã hội nhận được tin nhắn thông qua API postMessage, tiện ích đó 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 document.documentElement.clientWidth sẽ buộc bố cục vốn thường được đồng bộ hoá trước khi Chrome bật tính năng Tách biệt trang web. Tuy nhiên, khi bật tính năng Tách biệt trang web, việc bố cục lại tiện ích xã hội trên nhiều nguồn gốc hiện diễn ra một cách 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 tới trang đó, thì với tính năng Tách biệt trang web, khung nhận có thể chưa biết kích thước mới khi nhận được thông báo. Nói chung, điều này có thể làm hỏng trang nếu giả định rằng thay đổi bố cục sẽ truyền ngay lập tức đế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 lại, tài liệu cũ cũng như mọi tài liệu trong khung phụ được nhúng trong khung đó đều chạy trình xử lý unload. Nếu điều hướng mới diễn ra trong cùng một quy trình kết xuất đồ hoạ (ví dụ: cho điều hướng cùng nguồn gốc), thì trình xử lý unload của tài liệu cũ và các khung phụ của tài liệu đó có thể chạy trong một khoảng thời gian dài tuỳ ý trước khi cho phép thực hiện thao tác điều hướng mới.

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

Trong trường hợp này, các trình xử lý unload trong mọi khung hình 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 trong nhiều quá trình, ả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ì việc điều hướng new.example sẽ diễn ra trong một quy trình mới. Trình xử lý huỷ tải cho old.example và các khung phụ 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ý huỷ tải 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ý huỷ tải có thể không hoàn tất trước khi hết thời gian chờ, nên hành vi huỷ tải sẽ không đáng tin cậy hơn.

Với tính năng Tách biệt trang web, tất cả các hoạt động điều hướng trên nhiều trang web đều có thể thực hiện chéo quy trình, do đó tài liệu từ các trang web khác nhau không dùng chung một quy trình với nhau. Do đó, tình huống trên sẽ áp dụng trong nhiều trường hợp hơn và trình xử lý huỷ tải trong <iframe> thường 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 của tính năng Tách biệt trang web là thứ tự song song mới cho các trình xử lý huỷ tải: nếu không có Cách ly trang web, trình xử lý huỷ tải sẽ chạy theo thứ tự từ trên xuống nghiêm ngặt trên các khung. Tuy nhiên, với tính năng Tách biệt 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ệ 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ý huỷ 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 các lỗi khi trình xử lý huỷ tải khung phụ chưa thể sử dụng một số tính năng nhất định và đang tìm cách giải quyết.

Một trường hợp quan trọng đối với trình xử lý huỷ tải là gửi ping cuối phiên. Quy trình này thường được thực hiện như sau:

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

Một phương pháp hiệu quả hơn và hiệu quả hơn dựa trên thay đổi này là sử dụng navigator.sendBeacon:

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

Nếu cần kiểm soát yêu cầu này nhiều hơn, 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 khiến các trang web không đáng tin cậy khó truy cập hoặc lấy cắp thông tin từ tài khoản của bạn trên các trang web khác hơn bằng cách tách biệt mỗi trang web theo quy trình riêng. Theo đó, CORB cố gắng loại bỏ các tài nguyên dữ liệu nhạy cảm khỏi quá trình kết xuất. Các đề xuất của chúng tôi ở trên giúp bạn khai thác tối đa các tính năng bảo mật mới này.

Nhờ có Alex Moshchuk, Charlie Reis, Jason Miller, Nasko OSkov, Philip Walton, Shubhie 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.