Banyak aplikasi web perlu menampilkan konten yang dikontrol pengguna. Hal ini bisa sesederhana menayangkan gambar yang diupload pengguna (misalnya, foto profil), atau serumit merender HTML yang dikontrol pengguna (misalnya, tutorial pengembangan web). Hal ini selalu sulit dilakukan dengan aman, jadi kami telah berupaya menemukan solusi yang mudah, tetapi aman yang dapat diterapkan pada sebagian besar jenis aplikasi web.
Solusi klasik untuk mengisolasi konten yang tidak tepercaya
Solusi klasik untuk menayangkan konten yang dikontrol pengguna secara aman adalah dengan menggunakan apa yang dikenal sebagai domain sandbox. Gagasan dasarnya adalah jika domain utama aplikasi Anda adalah example.com, Anda dapat menayangkan semua konten yang tidak tepercaya di exampleusercontent.com. Karena kedua domain ini bersifat lintas situs, konten berbahaya di exampleusercontent.com tidak dapat memengaruhi example.com.
Pendekatan ini dapat digunakan untuk menyajikan semua jenis konten yang tidak tepercaya dengan aman, termasuk gambar, download, dan HTML. Meskipun mungkin tidak terlihat perlu menggunakan ini untuk gambar atau download, tindakan ini membantu menghindari risiko dari pengintaian konten, terutama di browser lama.
Domain sandbox banyak digunakan di seluruh industri dan telah berfungsi dengan baik sejak lama. Namun, ada dua kekurangan utama:
- Aplikasi sering kali perlu membatasi akses konten ke satu pengguna, yang memerlukan penerapan autentikasi dan otorisasi. Karena domain sandbox sengaja tidak membagikan cookie dengan domain aplikasi utama, hal ini sangat sulit dilakukan dengan aman. Untuk mendukung autentikasi, situs harus mengandalkan URL kemampuan, atau harus menetapkan cookie autentikasi terpisah untuk domain sandbox. Metode kedua ini sangat bermasalah di web modern karena banyak browser membatasi cookie lintas situs secara default.
- Meskipun konten pengguna diisolasi dari situs utama, konten tersebut tidak diisolasi dari konten pengguna lain. Hal ini menimbulkan risiko konten pengguna berbahaya menyerang data lain di domain sandbox (misalnya, dengan membaca data asal yang sama).
Perlu juga diperhatikan bahwa domain sandbox membantu memitigasi risiko phishing karena resource disegmentasikan dengan jelas ke domain yang terisolasi.
Solusi modern untuk menyajikan konten pengguna
Seiring waktu, web telah berkembang, dan kini ada cara yang lebih mudah dan aman untuk menayangkan konten yang tidak tepercaya. Ada banyak pendekatan berbeda di sini, jadi kami akan menguraikan dua solusi yang kami gunakan di Google.
Pendekatan 1: Menayangkan konten pengguna tidak aktif
Jika situs hanya perlu menayangkan konten pengguna yang tidak aktif (yaitu konten yang bukan HTML atau JavaScript, misalnya gambar dan download), hal ini kini dapat dilakukan dengan aman tanpa domain sandbox terisolasi. Ada dua langkah utama:
- Selalu tetapkan header
Content-Typeke jenis MIME terkenal yang didukung oleh semua browser dan tidak berisi konten aktif. Jika ragu,application/octet-streamadalah pilihan yang aman. - Selain itu, selalu tetapkan header respons untuk memastikan browser mengisolasi respons sepenuhnya.
| Header Respons | Tujuan |
|---|---|
X-Content-Type-Options: nosniff |
Mencegah pengintipan konten |
Content-Disposition: attachment; filename="download" |
Memicu download, bukan merender |
Content-Security-Policy: sandbox |
Mengisolasi konten seolah-olah disajikan di domain terpisah |
Content-Security-Policy: default-src ‘none' |
Menonaktifkan eksekusi JavaScript (dan penyertaan subresource apa pun) |
Cross-Origin-Resource-Policy: same-site |
Mencegah halaman disertakan di seluruh situs |
Kombinasi header ini memastikan bahwa respons hanya dapat dimuat sebagai subresource oleh aplikasi Anda, atau didownload sebagai file oleh pengguna. Selain itu, header ini memberikan beberapa lapisan perlindungan terhadap bug browser melalui header sandbox CSP dan batasan default-src. Secara keseluruhan, penyiapan yang diuraikan memberikan tingkat keyakinan yang tinggi bahwa respons yang disajikan dengan cara ini tidak dapat menyebabkan kerentanan injeksi atau isolasi.
Defense in depth
Meskipun solusi yang diusulkan merupakan pertahanan yang cukup memadai terhadap XSS, ada sejumlah langkah penguatan tambahan yang dapat Anda terapkan untuk memberikan lapisan keamanan tambahan:
- Tetapkan header
X-Content-Security-Policy: sandboxuntuk kompatibilitas dengan IE11. - Tetapkan header
Content-Security-Policy: frame-ancestors 'none'untuk mencegah penyematan endpoint. - Menyandbox konten pengguna di subdomain terisolasi dengan:
- Menayangkan konten pengguna di subdomain terisolasi (misalnya, Google menggunakan domain seperti
product.usercontent.google.com). - Tetapkan
Cross-Origin-Opener-Policy: same-origindanCross-Origin-Embedder-Policy: require-corpuntuk mengaktifkan isolasi lintas asal.
- Menayangkan konten pengguna di subdomain terisolasi (misalnya, Google menggunakan domain seperti
Pendekatan 2: Menyajikan konten pengguna aktif
Menayangkan konten aktif dengan aman (misalnya, gambar HTML atau SVG) juga dapat dilakukan tanpa kelemahan pendekatan domain sandbox klasik.
Opsi paling sederhana adalah memanfaatkan header Content-Security-Policy: sandbox untuk memberi tahu browser agar mengisolasi respons. Meskipun tidak semua browser web menerapkan isolasi proses untuk dokumen sandbox, penyempurnaan berkelanjutan pada model proses browser kemungkinan akan meningkatkan pemisahan konten sandbox dari aplikasi penyematan. Jika serangan SpectreJS dan kompromi perender berada di luar model ancaman Anda, maka penggunaan sandbox CSP kemungkinan merupakan solusi yang memadai.
Di Google, kami telah mengembangkan solusi yang dapat mengisolasi sepenuhnya konten aktif yang tidak tepercaya dengan memodernisasi konsep domain sandbox. Ide intinya adalah:
- Buat domain sandbox baru yang ditambahkan ke daftar akhiran publik. Misalnya, dengan menambahkan
exampleusercontent.comke PSL, Anda dapat memastikan bahwafoo.exampleusercontent.comdanbar.exampleusercontent.combersifat lintas situs dan dengan demikian sepenuhnya terisolasi satu sama lain. - Semua URL yang cocok dengan
*.exampleusercontent.com/shimakan dirutekan ke file shim statis. File shim ini berisi cuplikan HTML dan JavaScript singkat yang memproses pengendali peristiwamessagedan merender konten apa pun yang diterimanya. - Untuk menggunakannya, produk membuat iframe atau dialog untuk
$RANDOM_VALUE.exampleusercontent.com/shimdan menggunakanpostMessageuntuk mengirim konten yang tidak tepercaya ke shim untuk dirender. - Konten yang dirender diubah menjadi Blob dan dirender di dalam iframe sandbox.
Dibandingkan dengan pendekatan domain sandbox klasik, hal ini memastikan bahwa semua konten diisolasi sepenuhnya di situs yang unik. Selain itu, dengan membuat aplikasi utama menangani pengambilan data yang akan dirender, URL kemampuan tidak lagi diperlukan.
Kesimpulan
Bersama-sama, kedua solusi ini memungkinkan migrasi dari domain sandbox klasik seperti googleusercontent.com ke solusi yang lebih aman dan kompatibel dengan pemblokiran cookie pihak ketiga. Di Google, kami telah memigrasikan banyak produk untuk menggunakan solusi ini dan merencanakan lebih banyak migrasi untuk tahun depan.