HeatMapXHeatMapX
HargaMasuk

Menampilkan Pratinjau Situs Eksternal dengan Aman โ€” Implementasi Proxy + Sanitasi + iframe Sandbox

HeatMapX Engineering Team5 min read
  • engineering
  • security
  • nextjs
  • iframe

Ringkasan artikel ini

  • Memuat situs eksternal ke dalam iframe di origin milik sendiri berisiko membuat JS eksternal dapat menyentuh sesi milik sendiri
  • Solusinya adalah pertahanan berlapis: "proxy dengan perlindungan SSRF + penghapusan JS eksternal + CSP terbatas + iframe sandbox"
  • Sandbox yang terlalu ketat justru dapat menghentikan skrip milik sendiri. Ada jebakan berupa fitur yang tidak berfungsi karena lupa menambahkan allow-scripts

Fitur A/B testing HeatMapX memiliki kemampuan untuk "menampilkan pratinjau tampilan setelah perubahan (Variant B) yang diterapkan pada halaman target". Secara teknis, ini adalah proses yang cukup rumit, yaitu "menampilkan situs eksternal milik pengguna dengan aman di dalam iframe pada domain milik sendiri". Berikut ini kami bagikan desainnya beserta jebakan nyata yang kami temui.

Mengapa implementasi naif berbahaya

Jika HTML dari situs eksternal diambil apa adanya dan disajikan pada origin milik sendiri (misalnya heatmapx.com), maka <script> atau onclick= yang terdapat di dalam HTML tersebut akan dieksekusi dengan hak akses origin milik sendiri. Akibatnya, ada risiko cookie atau sesi login dapat dibaca oleh pihak lain. Hal ini harus dihindari.

Struktur pertahanan berlapis

Oleh karena itu, kami menerapkan lapisan-lapisan berikut secara bertumpuk.

1. Proxy dengan perlindungan SSRF

URL tujuan divalidasi, dan skema selain http/https ditolak. Selain itu, localhost, IP privat, serta endpoint metadata cloud (seperti 169.254.169.254) juga diblokir. Redirect tidak diikuti secara otomatis; sebaliknya, setiap tahap divalidasi ulang satu per satu menggunakan redirect: 'manual' agar tidak diarahkan ke jaringan internal.

2. Penghapusan JS eksternal (sanitasi)

Dari HTML yang diambil, tag <script>, handler inline on*=, dan skema javascript: dihapus. Ini karena JS milik situs pelanggan tidak perlu dijalankan untuk keperluan pratinjau (ketidakmampuan mereplikasi SPA secara sempurna adalah keterbatasan yang kami terima).

3. CSP terbatas dan base href

<base href> disisipkan tepat setelah <head> untuk menyelesaikan path relatif pada gambar dan CSS, sementara respons diberi CSP terbatas yang "tidak menjalankan JS eksternal". Gambar dan CSS tetap diizinkan agar tampilan tetap terlihat.

4. iframe sandbox

Terakhir, iframe pada sisi tampilan diberi atribut sandbox untuk mengisolasinya.

Jebakan yang kami temui: sandbox terlalu ketat

Pada fitur pratinjau, sebuah skrip kecil buatan sendiri yang "menerapkan perubahan (changeSet)" disisipkan ke dalam HTML yang diambil, lalu dijalankan di dalam iframe untuk mengubah tampilan. Namun, sandbox pada iframe pratinjau hanya memiliki allow-same-origin, dan allow-scripts tidak ditambahkan.

Akibatnya, skrip buatan sendiri pun tidak dieksekusi, sehingga terjadi bug di mana halaman asli ditampilkan tanpa perubahan yang diterapkan. iframe pada sisi editor untuk pengeditan berfungsi dengan benar karena menggunakan allow-scripts allow-same-origin, sehingga penyebabnya adalah ketidaksesuaian konfigurasi antara keduanya.

Perbaikannya sederhana, yaitu menyamakan sisi pratinjau menjadi allow-scripts allow-same-origin. Selain itu, kami juga menambahkan uji regresi untuk memvalidasi atribut sandbox pada iframe.

sandbox="allow-same-origin"  โ†’  sandbox="allow-scripts allow-same-origin"

Pelajaran yang didapat

  • Penyematan konten eksternal harus dipikirkan dengan pendekatan "pertahanan berlapis". Jangan bergantung pada satu langkah pengamanan saja.
  • sandbox bukan berarti "aman jika ditambahkan begitu saja" โ€” yang penting adalah mengizinkan hak akses secara tepat, hanya yang diperlukan. Jika terlalu ketat, fitur milik sendiri pun bisa berhenti berfungsi.
  • Untuk "dua jalur yang melakukan proses yang sama" (editor dan pratinjau), pastikan selalu bahwa atribut keamanannya sudah disamakan. Jika hanya salah satu yang diperbaiki, yang lain bisa jadi rusak.

Kesimpulan

Pratinjau situs eksternal yang aman dapat diwujudkan melalui pertahanan berlapis berupa perlindungan SSRF, penghapusan JS eksternal, CSP terbatas, dan iframe sandbox. Namun, hak akses pada sandbox dapat menjadi masalah baik jika kurang maupun jika berlebihan. Kasus lupa menambahkan allow-scripts kali ini adalah contoh khas dari hal tersebut.

Heatmap dari Claude Code โ€” mulai gratis.

Tempelkan satu tag tracker, terima analisis dan saran CRO dari CLI.