DOM Based XSS (Cross-Site Scripting) adalah kerentanan keamanan web yang terjadi ketika kode JavaScript sisi klien mengeksekusi data berbahaya secara tidak aman yang berasal dari sumber tidak tepercaya (source), lalu memasukkannya ke dalam objek Document Object Model (sink). Berbeda dengan Reflected atau Stored XSS di mana muatan skrip melewati server backend, DOM Based XSS terjadi sepenuhnya di dalam browser korban melalui manipulasi DOM yang cacat.
Mekanisme eksploitasi ini bermula ketika aplikasi web membaca data dari input pengguna yang dapat dimanipulasi—seperti parameter URL, fragment hash, atau cookie—tanpa melalui proses sanitasi atau validasi yang memadai. Data tersebut kemudian ditulis ulang ke dalam halaman HTML secara langsung menggunakan fungsi sink yang rentan, sehingga browser mengeksekusi skrip berbahaya tersebut sebagai bagian dari aplikasi yang sah.
Komponen Utama DOM Based XSS: Source dan Sink
Memahami cara kerja kerentanan ini menuntut pengenalan terhadap dua elemen inti, yaitu Source dan Sink. Source adalah properti JavaScript yang dapat dikendalikan atau diakses oleh penyerang, seperti location.search, location.hash, document.referrer, atau window.name. Data dari source ini diambil oleh skrip rentan tanpa pemeriksaan keamanan yang ketat.
Sementara itu, Sink adalah fungsi atau objek DOM yang dapat mengeksekusi kode atau merender HTML mentah ketika menerima masukan dari source. Contoh sink yang paling berbahaya meliputi eval(), document.write(), document.writeln(), serta manipulasi properti innerHTML seperti element.innerHTML dan element.outerHTML. Ketika data dari source mengalir ke sink tanpa pembersihan, eksekusi kode arbitrer pun terjadi.
| Komponen | Nama Objek / Properti | Deskripsi Teknis |
|---|---|---|
| Source | location.search |
Mengambil bagian kueri URL setelah tanda tanya (?). |
| Source | location.hash |
Mengambil fragmen URL setelah tanda pagar (#). |
| Sink | eval() |
Mengeksekusi string teks sebagai kode JavaScript. |
| Sink | document.write() |
Menulis string HTML secara langsung ke dalam dokumen. |
| Sink | innerHTML |
Menyuntikkan elemen HTML baru ke dalam elemen DOM yang ada. |
Alur Serangan dan Contoh Skenario Nyata
Skenario serangan tipikal melibatkan tautan pancingan yang dikirimkan kepada korban, misalnya https://example.com/page.html#<img src=x onerror=alert(document.cookie)>. Ketika korban mengklik tautan tersebut, browser memuat halaman page.html dan skrip internal aplikasi mengambil nilai dari location.hash untuk ditampilkan di dalam elemen halaman.
Jika kode aplikasi menggunakan perintah seperti document.getElementById('greeting').innerHTML = location.hash.substring(1);, maka string payload akan disuntikkan langsung ke dalam DOM. Browser menganggap tag <img> tersebut sebagai bagian sah dari halaman, memicu fungsi onerror, dan mengeksekusi perintah JavaScript penyerang untuk mencuri sesi pengguna.
Perbedaan DOM Based XSS dengan XSS Lainnya
Identifikasi yang akurat memerlukan pembeda jelas antara DOM Based XSS, Stored XSS, dan Reflected XSS. Pada Stored XSS, payload berbahaya disimpan secara permanen di database server dan dikirimkan ke setiap pengguna yang mengakses halaman terkait. Reflected XSS melibatkan pengiriman payload ke server melalui HTTP request, yang kemudian dipantulkan kembali dalam respons HTML.
Sebaliknya, pada DOM Based XSS, server sama sekali tidak pernah melihat payload tersebut dalam permintaan HTTP karena seluruh manipulasi terjadi di sisi klien (browser). Log server tidak akan mencatat keberadaan skrip berbahaya karena lalu lintas data berjalan secara lokal di dalam memori browser melalui manipulasi objek dokumen.
Strategi Pencegahan dan Mitigasi Keamanan
Mitigasi kerentanan ini menuntut pengembang web untuk menghindari penggunaan sink yang berbahaya dan menerapkan praktik pengkodean yang aman. Pengembang harus menghindari fungsi seperti eval() dan membatasi penggunaan innerHTML, serta menggantinya dengan properti yang aman seperti textContent atau innerText yang secara otomatis mengonversi karakter khusus menjadi entitas HTML.
Selain itu, penerapan Context-Aware Output Encoding dan penggunaan Content Security Policy (CSP) yang ketat dapat menghentikan eksekusi skrip inline yang tidak sah. Validasi input berbasis whitelist pada tingkat klien dan server juga memperkuat pertahanan terhadap segala upaya injeksi skrip yang memanfaatkan manipulasi DOM.