Banyak aplikasi web perlu menampilkan konten yang dikontrol pengguna. Hal ini dapat 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 ke sebagian besar jenis aplikasi web.
Solusi klasik untuk mengisolasi konten yang tidak tepercaya
Solusi klasik untuk menayangkan konten yang dikontrol pengguna dengan aman adalah menggunakan apa yang disebut domain sandbox. Ide 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 apa pun di exampleusercontent.com
tidak dapat memengaruhi example.com
.
Pendekatan ini dapat digunakan untuk menayangkan semua jenis konten tidak tepercaya dengan aman, termasuk gambar, download, dan HTML. Meskipun tampaknya tidak perlu menggunakan ini untuk gambar atau download, tindakan ini membantu menghindari risiko dari sniffing konten, terutama di browser lama.
Domain sandbox banyak digunakan di seluruh industri dan telah berfungsi dengan baik selama bertahun-tahun. Namun, ada dua kelemahan 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 yang 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 yang menyerang data lain di domain sandbox (misalnya, melalui pembacaan data dengan origin yang sama).
Perlu juga diperhatikan bahwa domain sandbox membantu memitigasi risiko phishing karena resource disegmentasikan dengan jelas ke domain yang terisolasi.
Solusi modern untuk menayangkan konten pengguna
Seiring waktu, web telah berkembang, dan kini ada cara yang lebih mudah dan lebih aman untuk menayangkan konten yang tidak tepercaya. Ada banyak pendekatan yang berbeda di sini, jadi kami akan menguraikan dua solusi yang saat ini banyak digunakan 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 yang terisolasi. Ada dua langkah utama:
- Selalu tetapkan header
Content-Type
ke jenis MIME yang dikenal luas dan didukung oleh semua browser serta dijamin tidak berisi konten aktif (jika ragu,application/octet-stream
adalah pilihan yang aman). - Selain itu, selalu tetapkan header respons di bawah untuk memastikan browser sepenuhnya mengisolasi respons.
Header Respons | Tujuan |
---|---|
X-Content-Type-Options: nosniff |
Mencegah sniffing konten |
Content-Disposition: attachment; filename="download" |
Memicu download, bukan rendering |
Content-Security-Policy: sandbox |
Menempatkan konten dalam sandbox seolah-olah konten tersebut ditayangkan di domain terpisah |
Content-Security-Policy: default-src ‘none' |
Menonaktifkan eksekusi JavaScript (dan penyertaan sub-resource apa pun) |
Cross-Origin-Resource-Policy: same-site |
Mencegah halaman disertakan secara lintas situs |
Kombinasi header ini memastikan bahwa respons hanya dapat dimuat sebagai sub-resource 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 di atas memberikan tingkat keyakinan yang tinggi bahwa respons yang ditayangkan dengan cara ini tidak dapat menyebabkan kerentanan injeksi atau isolasi.
Defense in depth
Meskipun solusi di atas secara umum cukup untuk melindungi dari XSS, ada sejumlah langkah hardening tambahan yang dapat Anda terapkan untuk memberikan lapisan keamanan tambahan:
- Tetapkan header
X-Content-Security-Policy: sandbox
untuk kompatibilitas dengan IE11. - Tetapkan header
Content-Security-Policy: frame-ancestors 'none'
untuk memblokir endpoint agar tidak disematkan. - Mengisolasi 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-origin
danCross-Origin-Embedder-Policy: require-corp
untuk mengaktifkan isolasi lintas asal.
- Menayangkan konten pengguna di subdomain terisolasi (misalnya, Google menggunakan domain seperti
Pendekatan 2: Menayangkan 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 saat ini tidak semua browser web menerapkan isolasi proses untuk dokumen sandbox, peningkatan berkelanjutan pada model proses browser kemungkinan akan meningkatkan pemisahan konten dengan sandbox dari aplikasi penyematan. Jika serangan SpectreJS dan kompromi perender berada di luar model ancaman Anda, menggunakan sandbox CSP mungkin merupakan solusi yang memadai.
Di Google, kami telah mengembangkan solusi yang dapat sepenuhnya mengisolasi konten aktif yang tidak tepercaya dengan memodernisasi konsep domain sandbox. Ide utamanya adalah untuk:
- Buat domain sandbox baru yang ditambahkan ke daftar akhiran publik. Misalnya, dengan menambahkan
exampleusercontent.com
ke PSL, Anda dapat memastikan bahwafoo.exampleusercontent.com
danbar.exampleusercontent.com
bersifat lintas situs sehingga sepenuhnya terisolasi satu sama lain. - Semua URL yang cocok dengan
*.exampleusercontent.com/shim
akan dirutekan ke file shim statis. File shim ini berisi cuplikan HTML dan JavaScript singkat yang memproses pengendali peristiwamessage
dan merender konten apa pun yang diterimanya. - Untuk menggunakannya, produk akan membuat iframe atau pop-up ke
$RANDOM_VALUE.exampleusercontent.com/shim
dan menggunakanpostMessage
untuk mengirim konten yang tidak tepercaya ke shim untuk dirender. - Konten yang dirender diubah menjadi Blob dan dirender di dalam iframe dengan sandbox.
Dibandingkan dengan pendekatan domain sandbox klasik, pendekatan ini memastikan bahwa semua konten sepenuhnya terisolasi di situs unik. Selain itu, dengan membuat aplikasi utama menangani pengambilan data yang akan dirender, Anda tidak perlu lagi menggunakan URL kemampuan.
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.