Isolasi Situs untuk developer web

Chrome 67 di desktop memiliki fitur baru bernama Isolasi Situs yang diaktifkan secara default. Artikel ini menjelaskan apa itu Isolasi Situs, mengapa diperlukan, dan mengapa developer web harus mengetahuinya.

Apa yang dimaksud dengan Isolasi Situs?

Internet digunakan untuk menonton video kucing dan mengelola dompet mata uang kripto, di antara hal-hal lainnya — tetapi Anda tidak ingin fluffycats.example memiliki akses ke cryptocoin Anda yang berharga. Untungnya, situs biasanya tidak dapat mengakses data satu sama lain di dalam browser berkat Kebijakan Asal Sama. Namun, situs berbahaya dapat mencoba mengabaikan kebijakan ini untuk menyerang situs lain, dan terkadang, bug keamanan ditemukan dalam kode browser yang menerapkan Kebijakan Origin yang Sama. Tim Chrome berupaya memperbaiki bug tersebut secepat mungkin.

Isolasi Situs adalah fitur keamanan di Chrome yang menawarkan garis pertahanan tambahan untuk membuat serangan tersebut tidak mungkin berhasil. Fitur ini memastikan bahwa halaman dari situs yang berbeda selalu dimasukkan ke dalam proses yang berbeda, yang masing-masing berjalan di sandbox yang membatasi apa yang boleh dilakukan proses. Fitur ini juga memblokir proses agar tidak menerima jenis data sensitif tertentu dari situs lain. Akibatnya, dengan Isolasi Situs, situs berbahaya akan jauh lebih sulit menggunakan serangan spekulatif side-channel seperti Spectre untuk mencuri data dari situs lain. Saat tim Chrome menyelesaikan penerapan tambahan, Isolasi Situs juga akan membantu meskipun halaman penyerang dapat melanggar beberapa aturan dalam prosesnya sendiri.

Isolasi Situs secara efektif mempersulit situs yang tidak tepercaya untuk mengakses atau mencuri informasi dari akun Anda di situs lain. Fitur ini menawarkan perlindungan tambahan terhadap berbagai jenis bug keamanan, seperti serangan side-channel Meltdown dan Spectre terbaru.

Untuk mengetahui detail selengkapnya tentang Isolasi Situs, lihat artikel kami di blog Keamanan Google.

Pemblokiran Baca Lintas Asal

Meskipun semua halaman lintas situs dimasukkan ke dalam proses terpisah, halaman masih dapat meminta beberapa sub-resource lintas situs secara sah, seperti gambar dan JavaScript. Halaman web berbahaya dapat menggunakan elemen <img> untuk memuat file JSON dengan data sensitif, seperti saldo bank Anda:

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

Tanpa Isolasi Situs, konten file JSON akan masuk ke memori proses perender, pada saat itu perender akan melihat bahwa file tersebut bukan format gambar yang valid dan tidak merender gambar. Namun, penyerang kemudian dapat mengeksploitasi kerentanan seperti Spectre untuk berpotensi membaca bagian memori tersebut.

Sebagai ganti menggunakan <img>, penyerang juga dapat menggunakan <script> untuk melakukan data sensitif ke memori:

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

Cross-Origin Read Blocking, atau CORB, adalah fitur keamanan baru yang mencegah konten balance.json memasuki memori proses perender berdasarkan jenis MIME-nya.

Mari kita uraikan cara kerja CORB. Situs dapat meminta dua jenis resource dari server:

  1. resource data seperti dokumen HTML, XML, atau JSON
  2. resource media seperti gambar, JavaScript, CSS, atau font

Situs dapat menerima resource data dari origin-nya sendiri atau dari origin lain dengan header CORS yang permisif seperti Access-Control-Allow-Origin: *. Di sisi lain, resource media dapat disertakan dari origin mana pun, bahkan tanpa header CORS yang permisif.

CORB mencegah proses perender menerima resource data lintas origin (yaitu HTML, XML, atau JSON) jika:

  • resource memiliki header X-Content-Type-Options: nosniff
  • CORS tidak mengizinkan akses ke resource secara eksplisit

Jika resource data lintas origin tidak memiliki header X-Content-Type-Options: nosniff yang ditetapkan, CORB akan mencoba mencuri isi respons untuk menentukan apakah itu HTML, XML, atau JSON. Hal ini diperlukan karena beberapa server web salah dikonfigurasi dan menayangkan gambar sebagai text/html, misalnya.

Resource data yang diblokir oleh kebijakan CORB ditampilkan ke proses sebagai kosong, meskipun permintaan masih terjadi di latar belakang. Akibatnya, halaman web berbahaya akan kesulitan menarik data lintas situs ke dalam prosesnya untuk mencuri.

Untuk keamanan yang optimal dan mendapatkan manfaat dari CORB, sebaiknya lakukan hal berikut:

  • Tandai respons dengan header Content-Type yang benar. (Misalnya, resource HTML harus ditayangkan sebagai text/html, resource JSON dengan jenis MIME JSON, dan resource XML dengan jenis MIME XML).
  • Memilih untuk tidak melakukan sniffing dengan menggunakan header X-Content-Type-Options: nosniff. Tanpa header ini, Chrome akan melakukan analisis konten cepat untuk mencoba mengonfirmasi bahwa jenisnya sudah benar, tetapi karena hal ini melakukan kesalahan dengan mengizinkan respons agar tidak memblokir hal-hal seperti file JavaScript, sebaiknya Anda melakukan hal yang benar dengan tegas.

Untuk mengetahui detail selengkapnya, lihat artikel CORB untuk developer web atau penjelasan CORB mendalam kami.

Mengapa developer web harus memperhatikan Isolasi Situs?

Sebagian besar, Isolasi Situs adalah fitur browser di balik layar yang tidak langsung ditampilkan kepada developer web. Misalnya, tidak ada API baru yang diekspos ke web untuk dipelajari. Secara umum, halaman web tidak akan dapat membedakan saat berjalan dengan atau tanpa Isolasi Situs.

Namun, ada beberapa pengecualian untuk aturan ini. Mengaktifkan Isolasi Situs akan disertai dengan beberapa efek samping halus yang dapat memengaruhi situs Anda. Kami mengelola daftar masalah Isolasi Situs umum, dan kami menjelaskan masalah yang paling penting di bawah.

Tata letak halaman penuh tidak lagi sinkron

Dengan Isolasi Situs, tata letak halaman penuh tidak lagi dijamin sinkron, karena frame halaman kini dapat tersebar di beberapa proses. Hal ini dapat memengaruhi halaman jika halaman mengasumsikan bahwa perubahan tata letak langsung diterapkan ke semua frame di halaman.

Sebagai contoh, mari kita pertimbangkan situs bernama fluffykittens.example yang berkomunikasi dengan widget sosial yang dihosting di 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>

Awalnya, lebar <iframe> widget media sosial adalah 123 piksel. Namun, halaman FluffyKittens mengubah lebar menjadi 456 piksel (memicu tata letak) dan mengirim pesan ke widget sosial, yang memiliki kode berikut:

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

Setiap kali widget sosial menerima pesan melalui postMessage API, widget tersebut akan mencatat lebar elemen <html> root-nya ke dalam log.

Nilai lebar mana yang dicatat dalam log? Sebelum Chrome mengaktifkan Isolasi Situs, jawabannya adalah 456. Mengakses document.documentElement.clientWidth akan memaksa tata letak, yang sebelumnya sinkron sebelum Chrome mengaktifkan Isolasi Situs. Namun, dengan mengaktifkan Isolasi Situs, tata letak ulang widget sosial lintas origin sekarang terjadi secara asinkron dalam proses terpisah. Dengan demikian, jawaban kini juga dapat berupa 123, yaitu nilai width lama.

Jika halaman mengubah ukuran <iframe> lintas origin, lalu mengirim postMessage ke halaman tersebut, dengan Isolasi Situs, frame penerima mungkin belum mengetahui ukuran barunya saat menerima pesan. Secara umum, hal ini dapat merusak halaman jika halaman mengasumsikan bahwa perubahan tata letak segera diterapkan ke semua bingkai di halaman.

Dalam contoh khusus ini, solusi yang lebih andal akan menetapkan width di frame induk, dan mendeteksi perubahan tersebut di <iframe> dengan memproses peristiwa resize.

Pengendali penghapusan muatan mungkin lebih sering habis waktunya

Saat frame menavigasi atau menutup, dokumen lama serta dokumen subframe yang disematkan di dalamnya akan menjalankan pengendali unload-nya. Jika navigasi baru terjadi dalam proses perender yang sama (misalnya untuk navigasi dengan origin yang sama), pengendali unload dokumen lama dan subframe-nya dapat berjalan selama waktu yang lama secara arbitrer sebelum mengizinkan navigasi baru untuk dilakukan.

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

Dalam situasi ini, pengendali unload di semua frame sangat andal.

Namun, meskipun tanpa Isolasi Situs, beberapa navigasi frame utama bersifat lintas proses, yang memengaruhi perilaku pengendali penghapus muatan. Misalnya, jika Anda membuka old.example ke new.example dengan mengetik URL di kolom URL, navigasi new.example akan terjadi dalam proses baru. Pengendali unload untuk old.example dan subframe-nya berjalan dalam proses old.example di latar belakang, setelah halaman new.example ditampilkan, dan pengendali unload lama dihentikan jika tidak selesai dalam waktu tunggu tertentu. Karena pengendali penghapusan muatan mungkin tidak selesai sebelum waktu tunggu habis, perilaku penghapusan muatan kurang andal.

Dengan Isolasi Situs, semua navigasi lintas situs menjadi lintas proses, sehingga dokumen dari situs yang berbeda tidak berbagi proses satu sama lain. Akibatnya, situasi di atas berlaku dalam lebih banyak kasus, dan pengendali penghapusan muatan di <iframe> sering kali memiliki perilaku latar belakang dan waktu tunggu yang dijelaskan di atas.

Perbedaan lain yang dihasilkan dari Site Isolation adalah pengurutan paralel baru pengendali penghapusan muatan: tanpa Site Isolation, pengendali penghapusan muatan berjalan dalam urutan top-down yang ketat di seluruh frame. Namun, dengan Isolasi Situs, pengendali penghapusan muatan berjalan secara paralel di berbagai proses.

Hal ini merupakan konsekuensi mendasar dari mengaktifkan Isolasi Situs. Tim Chrome sedang berupaya meningkatkan keandalan pengendali penghapusan muatan untuk kasus penggunaan umum, jika memungkinkan. Kami juga mengetahui bug saat pengendali penghapusan muatan subframe belum dapat menggunakan fitur tertentu dan sedang bekerja untuk mengatasinya.

Kasus penting untuk pengendali penghapusan muatan adalah mengirim ping akhir sesi. Hal ini biasanya dilakukan sebagai berikut:

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

Pendekatan yang lebih baik dan lebih andal sehubungan dengan perubahan ini adalah menggunakan navigator.sendBeacon:

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

Jika memerlukan kontrol lebih besar atas permintaan, Anda dapat menggunakan opsi keepalive Fetch API:

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

Kesimpulan

Isolasi Situs mempersulit situs yang tidak tepercaya untuk mengakses atau mencuri informasi dari akun Anda di situs lain dengan mengisolasi setiap situs ke dalam prosesnya sendiri. Sebagai bagian dari itu, CORB mencoba menyimpan resource data sensitif dari proses perender. Rekomendasi kami di atas memastikan Anda mendapatkan hasil maksimal dari fitur keamanan baru ini.

Terima kasih kepada Alex Moshchuk, Charlie Reis, Jason Miller, Nasko Oskov, Philip Walton, Shubhi Panicker, dan Thomas Steiner yang telah membaca versi draf artikel ini dan memberikan masukan.