Menghosting data pengguna dengan aman di aplikasi web modern

David Dworken
David Dworken

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 secara aman, jadi kami telah bekerja untuk menemukan solusi yang mudah namun 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 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 menyajikan semua jenis konten tidak tepercaya dengan aman, termasuk gambar, download, dan HTML. Meskipun penggunaan metode ini untuk gambar atau download mungkin tidak diperlukan, hal tersebut akan membantu menghindari risiko penyadapan konten, terutama di browser lama.
Domain sandbox digunakan secara luas di seluruh industri dan telah bekerja dengan baik untuk waktu yang lama. Namun, mereka memiliki dua kelemahan utama:

  • Aplikasi sering kali perlu membatasi akses konten untuk satu pengguna, yang memerlukan penerapan autentikasi dan otorisasi. Karena domain sandbox sengaja tidak membagikan cookie dengan domain aplikasi utama, hal ini sangat sulit dilakukan secara 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, di mana banyak browser membatasi cookie lintas situs secara default.
  • Meskipun konten pengguna diisolasi dari situs utama, konten tersebut tidak terisolasi dari konten pengguna lainnya. Hal ini menimbulkan risiko konten pengguna berbahaya yang menyerang data lain di domain sandbox (misalnya, melalui pembacaan data origin yang sama).

Perlu juga dicatat bahwa domain {i>sandbox <i}membantu mengurangi risiko {i>phishing<i} karena sumber daya telah disegmentasikan dengan jelas ke dalam 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 yang berbeda di sini, jadi kami akan menguraikan dua solusi yang saat ini digunakan secara luas di Google.

Pendekatan 1: Menyajikan konten pengguna yang tidak aktif

Jika situs hanya perlu menayangkan konten pengguna yang tidak aktif (yaitu konten yang bukan HTML atau JavaScript, misalnya gambar dan download), tindakan ini sekarang 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 dan 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 penyadapan konten

Content-Disposition: attachment; filename="download"

Memicu download, bukan rendering

Content-Security-Policy: sandbox

Sandbox 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 lintas situs

Kombinasi header ini memastikan bahwa respons hanya dapat dimuat sebagai subresource oleh aplikasi Anda, atau didownload sebagai file oleh pengguna. Selain itu, header memberikan perlindungan berlapis terhadap bug browser melalui header sandbox CSP dan pembatasan default-src. Secara keseluruhan, penyiapan yang diuraikan di atas memberikan tingkat keyakinan yang 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 umumnya cukup memadai terhadap XSS, ada sejumlah langkah pengerasan 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.
  • Lakukan sandbox konten pengguna di subdomain yang terisolasi dengan:
    • Menayangkan konten pengguna di subdomain yang terisolasi (misalnya, Google menggunakan domain seperti product.usercontent.google.com).
    • Tetapkan Cross-Origin-Opener-Policy: same-origin dan Cross-Origin-Embedder-Policy: require-corp untuk mengaktifkan isolasi lintas asal.

Pendekatan 2: Menyajikan 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 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 sandbox, peningkatan berkelanjutan pada model proses browser kemungkinan akan meningkatkan pemisahan konten dalam sandbox dari penyematan aplikasi. Jika serangan SpectreJS dan penyusupan perender berada di luar model ancaman Anda, penggunaan sandbox CSP kemungkinan merupakan solusi yang cukup.
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 bahwa foo.exampleusercontent.com dan bar.exampleusercontent.com bersifat 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 peristiwa message dan merender konten apa pun yang diterimanya.
  • Untuk menggunakan ini, produk akan membuat iframe atau pop-up ke $RANDOM_VALUE.exampleusercontent.com/shim dan menggunakan postMessage untuk mengirim konten tidak tepercaya ke shim untuk rendering.
  • Konten yang dirender akan diubah menjadi Blob dan dirender di dalam frame dengan sandbox.

Dibandingkan dengan pendekatan domain {i>sandbox<i} klasik, hal ini memastikan bahwa semua konten sepenuhnya terisolasi di sebuah situs yang unik. Dan, karena memiliki aplikasi utama yang berurusan dengan pengambilan data yang akan dirender, 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 rencana migrasi lainnya untuk tahun depan.