Stored Cross-Site Scripting (XSS) terjadi ketika aplikasi web menyimpan input pengguna yang tidak divalidasi—biasanya melalui formulir komentar, profil pengguna, atau log—dan menampilkannya kembali kepada pengguna lain tanpa proses sanitasi atau encoding yang memadai. Pencegahan mutlak memerlukan pendekatan berlapis, mulai dari validasi ketat di sisi server hingga context-aware output encoding.
Strategi pencegahan utama berfokus pada penanganan data saat masuk (input validation), saat disimpan (safe storage), dan terutama saat dirender kembali ke peramban pengguna (output encoding). Mengandalkan validasi sisi klien saja sangat rentan dilewati oleh penyerang menggunakan perangkat seperti Burp Suite.
Metode Pencegahan Stored XSS
Tabel berikut membandingkan tiga teknik esensial dalam mitigasi kerentanan Stored XSS beserta fungsi dan tingkat efektivitasnya:
| Teknik Keamanan | Fase Implementasi | Cara Kerja | Tingkat Efektivitas |
|---|---|---|---|
| Output Encoding | Saat Data Dirender (Response) | Mengubah karakter khusus (seperti <, >, &) menjadi entitas HTML yang aman. |
Sangat Tinggi (Pertahanan Utama) |
| Input Sanitization | Saat Data Diterima (Server-side) | Membersihkan atau menghapus tag berbahaya (seperti <script>) menggunakan pustaka tepercaya. |
Tinggi (Untuk input teks kaya/rich text) |
| Content Security Policy (CSP) | Header HTTP / Browser | Membatasi sumber eksekusi skrip dan melarang eksekusi inline script. | Sangat Tinggi (Pertahanan Lapis Kedua) |
Contoh Implementasi Kode Pencegahan (PHP)
Berikut adalah contoh kode nyata menggunakan PHP untuk menerapkan output encoding dengan fungsi htmlspecialchars() guna mencegah eksekusi skrip berbahaya saat data ditampilkan ke halaman web:
<?php
// Koneksi database dan pengambilan data tersimpan
$stmt = $pdo->prepare("SELECT comment_text FROM comments WHERE post_id = ?");
$stmt->execute([$postId]);
$comments = $stmt->fetchAll();
foreach ($comments as $comment) {
// ENT_QUOTES menangani petik tunggal dan ganda
// UTF-8 memastikan karakter multibahasa aman
$safe_comment = htmlspecialchars($comment['comment_text'], ENT_QUOTES, 'UTF-8');
echo '<div class="comment-box">' . $safe_comment . '</div>';
}
?>
Contoh Implementasi dengan DOMPurify (JavaScript / Frontend Rich Text)
Jika aplikasi Anda memerlukan input teks kaya (seperti editor blog atau forum) di mana beberapa tag HTML diizinkan, Anda wajib menggunakan pembersih berbasis DOM seperti DOMPurify sebelum merender HTML tersebut:
// Sertakan DOMPurify melalui CDN atau npm
// <script src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/3.0.8/purify.min.js"></script>
const userInputStoredInDatabase = '<img src=x onerror=alert(1)><p>Komentar aman.</p>';
// Membersihkan skrip berbahaya tetapi mempertahankan tag <p>
const cleanHTML = DOMPurify.sanitize(userInputStoredInDatabase);
document.getElementById('comment-section').innerHTML = cleanHTML;
Konfigurasi Content Security Policy (CSP)
Tambahkan header HTTP berikut pada aplikasi web Anda untuk memitigasi dampak XSS jika terjadi kelalaian pada kode aplikasi:
Header set Content-Security-Policy "default-src 'self'; script-src 'self'; object-src 'none';"
Langkah-Langkah Teknis Audit & Perbaikan
- Identifikasi semua titik penyimpanan data (kolom database yang menerima input langsung dari pengguna).
- Pastikan tidak ada penggunaan fungsi cetak mentah (seperti
echolangsung dari database tanpa fungsi escape). - Terapkan validasi tipe data yang ketat pada sisi server (backend) sebelum query penyimpanan dieksekusi.
- Aktifkan flag
HttpOnlypada cookie sesi untuk mencegah pencurian token sesi melalui injeksi skrip XSS.
Troubleshooting Lapangan
Jika karakter khusus tetap tereksekusi di peramban:
- Periksa apakah header
Content-Typehalaman sudah diatur dengan benar (misalnyatext/html; charset=UTF-8). Peramban lama dapat menebak tipe konten (content sniffing) jika header tidak jelas. - Pastikan encoding dilakukan tepat sebelum variabel dicetak ke DOM, bukan saat data dimasukkan ke database, untuk menghindari penyimpanan ganda entitas HTML (double encoding).