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). Selalu sulit untuk dilakukan dengan aman, jadi kami telah berupaya menemukan solusi yang mudah namun aman yang dapat diterapkan ke sebagian besar jenis aplikasi web.
Solusi klasik untuk mengisolasi konten tidak tepercaya
Solusi klasik untuk menayangkan konten yang dikontrol pengguna dengan aman adalah dengan menggunakan 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 lintas situs, konten berbahaya apa pun di exampleusercontent.com
tidak dapat memengaruhi example.com
.
Pendekatan ini dapat digunakan untuk menayangkan dengan aman semua jenis konten yang tidak tepercaya, termasuk gambar, download, dan HTML. Meskipun sepertinya tidak diperlukan untuk menggunakan gambar atau download, melakukan hal ini membantu menghindari risiko dari penyadapan konten, terutama di browser lama.
Domain sandbox digunakan secara luas di seluruh industri dan telah berfungsi dengan baik untuk waktu yang lama. Tapi, mereka memiliki dua
kelemahan utama:
- Aplikasi sering kali perlu membatasi akses konten ke satu pengguna, yang memerlukan penerapan autentikasi dan otorisasi. Karena domain {i>sandbox<i} sengaja tidak berbagi 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 ini tidak diisolasi dari konten pengguna lainnya. Hal ini menimbulkan risiko konten pengguna yang berbahaya menyerang data lain di domain sandbox (misalnya, melalui membaca data origin yang sama).
Perlu diketahui juga bahwa domain sandbox membantu mengurangi risiko phishing, karena resource disegmentasikan dengan jelas ke domain yang terisolasi.
Solusi modern untuk menayangkan konten pengguna
Seiring waktu, web telah berkembang, dan sekarang ada cara yang lebih mudah dan aman untuk menyajikan konten yang tidak tepercaya. Ada banyak pendekatan yang berbeda di sini, jadi kami akan menguraikan dua solusi yang saat ini digunakan secara luas di Google.
Pendekatan 1: Menayangkan konten pengguna yang tidak aktif
Jika situs hanya perlu menyajikan konten pengguna yang tidak aktif (yaitu konten yang bukan HTML atau JavaScript, misalnya gambar dan download), hal ini sekarang dapat dilakukan dengan aman tanpa domain sandbox terisolasi. Ada dua langkah penting:
- Selalu tetapkan header
Content-Type
ke jenis MIME yang dikenal luas dan didukung oleh semua browser dan dijamin tidak berisi konten aktif (jika ragu,application/octet-stream
adalah pilihan yang aman). - Selain itu, selalu setel header respons di bawah untuk memastikan browser mengisolasi respons sepenuhnya.
Header Respons | Tujuan |
---|---|
X-Content-Type-Options: nosniff |
Mencegah penyadapan konten |
Content-Disposition: attachment; filename="download" |
Memicu download, bukan rendering |
Content-Security-Policy: sandbox |
Melakukan sandbox konten seolah-olah ditayangkan 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 lintas situs |
Kombinasi header ini memastikan bahwa respons hanya bisa dimuat sebagai subsumber daya oleh aplikasi Anda, atau diunduh sebagai file oleh pengguna. Selain itu, header ini memberikan perlindungan berlapis terhadap bug browser melalui header sandbox CSP dan pembatasan default-src
. Secara keseluruhan, penyiapan yang diuraikan di atas memberikan tingkat keyakinan tinggi bahwa respons yang diberikan dengan cara ini tidak dapat menyebabkan kerentanan injeksi atau isolasi.
Defense in depth
Meskipun solusi di atas mewakili pertahanan yang secara umum memadai terhadap XSS, ada sejumlah tindakan hardening tambahan yang dapat Anda terapkan untuk memberikan lapisan keamanan tambahan:
- Setel header
X-Content-Security-Policy: sandbox
untuk kompatibilitas dengan IE11. - Tetapkan header
Content-Security-Policy: frame-ancestors 'none'
untuk memblokir endpoint agar tidak disematkan. - Konten pengguna sandbox di subdomain yang terisolasi dengan:
- Menyajikan konten pengguna di subdomain yang 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 origin.
- Menyajikan konten pengguna di subdomain yang terisolasi (misalnya, Google menggunakan domain seperti
Pendekatan 2: Menayangkan konten pengguna aktif
Penyajian konten aktif dengan aman (misalnya, gambar HTML atau SVG) juga dapat dilakukan tanpa kelemahan pendekatan domain {i>sandbox<i} klasik.
Opsi yang paling sederhana adalah memanfaatkan header Content-Security-Policy: sandbox
untuk memberi tahu browser agar mengisolasi respons. Meskipun tidak semua browser web saat ini menerapkan isolasi proses untuk dokumen dengan sandbox, peningkatan yang berkelanjutan pada model proses browser kemungkinan akan meningkatkan pemisahan konten dalam sandbox dari aplikasi yang disematkan. Jika serangan SpectreJS dan penyusupan perender berada di luar model ancaman Anda, penggunaan 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 intinya 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
adalah lintas situs sehingga sepenuhnya terisolasi satu sama lain. - URL yang cocok dengan
*.exampleusercontent.com/shim
semuanya dirutekan ke file shim statis. File shim ini berisi cuplikan HTML dan JavaScript singkat yang memproses pengendali peristiwamessage
dan merender konten apa pun yang diterima. - Untuk menggunakannya, produk akan membuat iframe atau pop-up ke
$RANDOM_VALUE.exampleusercontent.com/shim
dan menggunakanpostMessage
untuk mengirim konten tidak tepercaya ke shim untuk dirender. - Konten yang dirender akan diubah menjadi Blob dan dirender di dalam iframe dengan sandbox.
Dibandingkan dengan pendekatan domain {i>sandbox<i} klasik, hal ini memastikan bahwa semua konten sepenuhnya terisolasi di situs yang unik. Selain itu, dengan membuat aplikasi utama berurusan dengan 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 yang kompatibel dengan pemblokiran cookie pihak ketiga. Di Google, kami telah memigrasikan banyak produk untuk menggunakan solusi ini dan memiliki lebih banyak rencana migrasi untuk tahun depan.