Menghosting data pengguna dengan aman di aplikasi web modern

David Dworken
David Dworken

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 dan Cross-Origin-Embedder-Policy: require-corp untuk mengaktifkan isolasi lintas origin.

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 bahwa foo.exampleusercontent.com dan bar.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 peristiwa message dan merender konten apa pun yang diterima.
  • Untuk menggunakannya, produk akan membuat iframe atau pop-up ke $RANDOM_VALUE.exampleusercontent.com/shim dan menggunakan postMessage 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.