- Musuh Utama Bukan Hacker, Tapi SINK
Dalam analisis keamanan terutama DOM-Base XSS, alur data dimulai dari Source dan berahir di di Sink.
- Apa itu data source
Source adalah titik data dari pengguna masuk. Contoh source yang dikenal saat ini : location.hash; document.referrer.
- Apa itu execution sink (titik bahaya) Fungsi atau property di browser yang dapat mengeksekusi kode jika diberikan masukan data mentah. Contoh: innerHTML; eval (); setTimeout()).
- Sementara HOOKS, dalam konteks framework modern (seperti React/Vue) adalah fungsi perantara digunakan untuk memperoses data sebelum sampai ke Sink.
Dalam sisi defensive dengan melakukan pemantauan Sink, Depelover harus menghindari Sink berbahaya (seperti innerHTML) dan segera menggantinya dengan textContent
- innerHTML Vs textContent
Dalam manipulasi DOM untuk mencegah XSS. Aksi innerHTML mengambil string dan merendernya sebagai HTML, sedangkan textContent mengambil string dan merendernya secara murni sebagai teks mentah, meskipun input berisi kode script berowser tidak akan pernah mengeksekusinya.
Contoh kode innerHTML Vs textContent :
- innerHTML – Versi Berbahaya
Metode ini akan merender string apa pun sebagai kode HTML. Jika data berisi script, browser akan mengeksekusinya.
javascript
// Simulasi data dari input pengguna atau database yang disusupi
const userInput = "<img src='x' onerror='alert(\"Akun Anda diretas!\")'>";
// Target elemen di halaman
const displayArea = document.getElementById('display');
// BERBAHAYA: Browser akan mencoba merender tag <img>
// dan menjalankan atribut 'onerror'
displayArea.innerHTML = userInput;
Risiko: Penyerang bisa mencuri cookie, melakukan pengalihan (redirect), atau merusak tampilan situs.
2. textContent – Versi Aman
Metode ini memperlakukan semua data murni sebagai teks biasa. Karakter seperti < atau > tidak akan dianggap sebagai tag HTML.
javascript
// Simulasi data yang sama
const userInput = "<img src='x' onerror='alert(\"Akun Anda diretas!\")'>";
// Target elemen di halaman
const displayArea = document.getElementById('display');
// AMAN: Browser hanya akan menampilkan tulisan mentah tersebut di layar
// Tanpa mengeksekusi gambar atau script di dalamnya
displayArea.textContent = userInput;
Hasil: Di layar akan muncul tulisan: <img src=’x’ onerror=’alert(“Akun Anda diretas!”)’> bukannya menjalankan perintah alert
- Bila harus menggunakan innerHTML karena kebutuhan, maka cara bijak Adalah dengan mengaktifkan DOMPurify dalam kode yang dibuat.
Contoh Implementasi Gabungan
Berikut adalah cara menggunakan DOMPurify untuk membersihkan data sebelum dimasukkan ke innerHTML:
javascript
// 1. Muat library DOMPurify (bisa via CDN untuk percobaan)
// <script src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/3.0.1/purify.min.js"></script>
// 2. Data "kotor" yang mengandung serangan XSS dan format teks
const dirtyHTML = `
<b>Halo!</b> Ini teks tebal,
<i>ini miring</i>,
<img src=x onerror="alert('Hacked!')">
<script>console.log('Script jahat')</script>`;
// 3. Proses sanitasi dengan DOMPurify
// Ia akan menghapus <script> dan atribut 'onerror' secara otomatis
const cleanHTML = DOMPurify.sanitize(dirtyHTML);
// 4. Masukkan hasil yang sudah bersih ke innerHTML
document.getElementById('content').innerHTML = cleanHTML;
// HASILNYA:
// Browser hanya akan merender: <b>Halo!</b> Ini teks tebal, <i>ini miring</i>, <img src="x">
// Script alert dan console.log TIDAK AKAN PERNAH berjalan.
Mengapa Kombinasi Ini Sangat Kuat?
Akurasi Tinggi: DOMPurify menggunakan mesin parsing yang sama dengan browser, sehingga ia mengerti persis kode mana yang bisa berubah menjadi serangan.
Fleksibel: Anda bisa mengatur tag apa saja yang diizinkan. Misalnya, hanya boleh <b> dan <i>, tapi dilarang keras <img>.
Layer Terakhir: Ini adalah “jaring pengaman” terakhir di sisi klien (frontend) sebelum data benar-benar tampil di layar pengguna.